{ "version": "https://jsonfeed.org/version/1", "title": "Jason R Briggs (all content)", "home_page_url": "https://jasonrbriggs.com", "feed_url": "https://jasonrbriggs.com/feed.json", "items": [ { "id": "https://jasonrbriggs.com/micro/2023/07/06/202458.html", "title": "Microblog posted at 06 Jul 2023 19:24:58", "url": "https://jasonrbriggs.com/micro/2023/07/06/202458.html", "content_text": "Twitter is threatening to sue Meta over Threads [semafor.com/article/07/06/2023/twitter-is-threatening-to-sue-meta...](https://www.semafor.com/article/07/06/2023/twitter-is-threatening-to-sue-meta-over-threads) :popcorn:", "content_html": "
Twitter is threatening to sue Meta over Threads semafor.com/article/07/06/2023/twitter-is-threatening-to-sue-meta... 🍿
", "date_published": "2023-07-06T19:24:58+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/08/183350.html", "title": "Microblog posted at 08 May 2023 17:33:50", "url": "https://jasonrbriggs.com/micro/2023/05/08/183350.html", "content_text": "ActivityPub on a (mostly) static site: [jasonrbriggs.com/journal/2023/05/08/activitypub-on-a-static-site.html](https://jasonrbriggs.com/journal/2023/05/08/activitypub-on-a-static-site.html)", "content_html": "ActivityPub on a (mostly) static site: jasonrbriggs.com/journal/2023/05/08/activitypub-on-a-static-site.html
", "date_published": "2023-05-08T17:33:50+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/08/083033.html", "title": "Microblog posted at 08 May 2023 07:30:33", "url": "https://jasonrbriggs.com/micro/2023/05/08/083033.html", "content_text": "@billbennett@mastodon.nz Goldfish. Are they nutritious...? :grinning_face_with_smiling_eyes: (replyto: https://mastodon.social/@billbennett@mastodon.nz/110330536796892248)", "content_html": "@billbennett Goldfish. Are they nutritious...? 😄 (replyto: mastodon.social/@billbennett@mastodon.nz/110330536796892248)
", "date_published": "2023-05-08T07:30:33+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/07/092021.html", "title": "Microblog posted at 07 May 2023 08:20:21", "url": "https://jasonrbriggs.com/micro/2023/05/07/092021.html", "content_text": "Interesting change in my own behaviour, when I see [Hacker News](https://news.ycombinator.com/) posts which link to twitter, I've stopped bothering to click... in fact, I now find them annoying. I wonder how many other folk feel the same level of apathy...", "content_html": "Interesting change in my own behaviour, when I see Hacker News posts which link to twitter, I've stopped bothering to click... in fact, I now find them annoying. I wonder how many other folk feel the same level of apathy...
", "date_published": "2023-05-07T08:20:21+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/03/213631.html", "title": "Microblog posted at 03 May 2023 20:36:31", "url": "https://jasonrbriggs.com/micro/2023/05/03/213631.html", "content_text": "The second edition of Python for Kids is a part of the [Python Humble Bundle](https://www.humblebundle.com/books/python-no-starch-books) - along with a bunch of other No Starch Python books. Pay what you want... but it's for charity (supporting the Python Software Foundation), so why not pay more than you want? ツ", "content_html": "The second edition of Python for Kids is a part of the Python Humble Bundle - along with a bunch of other No Starch Python books. Pay what you want... but it's for charity (supporting the Python Software Foundation), so why not pay more than you want? ツ
", "date_published": "2023-05-03T20:36:31+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/02/214439.html", "title": "Microblog posted at 02 May 2023 20:44:39", "url": "https://jasonrbriggs.com/micro/2023/05/02/214439.html", "content_text": "@andOlga@mastodon.social Thx. Good to know it's not just me then... (replyto: https://mastodon.social/@andOlga/110300644796824360)", "content_html": "@andOlga Thx. Good to know it's not just me then... (replyto: mastodon.social/@andOlga/110300644796824360)
", "date_published": "2023-05-02T20:44:39+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/02/213908.html", "title": "Microblog posted at 02 May 2023 20:39:08", "url": "https://jasonrbriggs.com/micro/2023/05/02/213908.html", "content_text": "Trying to answer my own question, (replyto: https://jasonrbriggs.com/micro/2023/05/02/195233.html) I've added language attributes to my json in the hope the Translate link goes away...", "content_html": "Trying to answer my own question, (replyto: jasonrbriggs.com/micro/2023/05/02/195233.html) I've added language attributes to my json in the hope the Translate link goes away...
", "date_published": "2023-05-02T20:39:08+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/02/195233.html", "title": "Microblog posted at 02 May 2023 18:52:33", "url": "https://jasonrbriggs.com/micro/2023/05/02/195233.html", "content_text": "Another oddity about the Mastodon integration with my (mostly) static site - why am I seeing a translate link with every post? Assume I'm missing something in my metadata...?", "content_html": "Another oddity about the Mastodon integration with my (mostly) static site - why am I seeing a translate link with every post? Assume I'm missing something in my metadata...?
", "date_published": "2023-05-02T18:52:33+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/01/094809.html", "title": "Microblog posted at 01 May 2023 08:48:09", "url": "https://jasonrbriggs.com/micro/2023/05/01/094809.html", "content_text": "@billbennett@mastodon.nz If anything like me, procrastinate until just about the week before it's due... and ignore months of reminders from HMRC... (replyto: https://mastodon.social/@billbennett@mastodon.nz/110292469955548357)", "content_html": "@billbennett If anything like me, procrastinate until just about the week before it's due... and ignore months of reminders from HMRC... (replyto: mastodon.social/@billbennett@mastodon.nz/110292469955548357)
", "date_published": "2023-05-01T08:48:09+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/05/01/082331.html", "title": "Microblog posted at 01 May 2023 07:23:31", "url": "https://jasonrbriggs.com/micro/2023/05/01/082331.html", "content_text": "Some annoyances with my Mastodon integration thus far: no green tick on my profile for my site, Mastodon doesn't seem to be updated with the latest info from my actor file, I've yet to setup any notifications for inbox deliveries (so a very manual process), I need to figure out a good way to handle replies... I'm sure there are others.", "content_html": "Some annoyances with my Mastodon integration thus far: no green tick on my profile for my site, Mastodon doesn't seem to be updated with the latest info from my actor file, I've yet to setup any notifications for inbox deliveries (so a very manual process), I need to figure out a good way to handle replies... I'm sure there are others.
", "date_published": "2023-05-01T07:23:31+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/04/30/222820.html", "title": "Microblog posted at 30 Apr 2023 21:28:20", "url": "https://jasonrbriggs.com/micro/2023/04/30/222820.html", "content_text": "So I **think** I've managed to get microposts on my site federating to Mastodon. This post will prove it though... :-D", "content_html": "So I think I've managed to get microposts on my site federating to Mastodon. This post will prove it though... :-D
", "date_published": "2023-04-30T21:28:20+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/04/30/094254.html", "title": "Microblog posted at 30 Apr 2023 08:42:54", "url": "https://jasonrbriggs.com/micro/2023/04/30/094254.html", "content_text": "[Mastodon and http sig](https://jasonrbriggs.com/journal/2023/04/30/mastodon-and-http-sig.html) (a post about trying to submit an Accept response to a Follow activity on Mastodon, with a static site)", "content_html": "Mastodon and http sig (a post about trying to submit an Accept response to a Follow activity on Mastodon, with a static site)
", "date_published": "2023-04-30T08:42:54+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/03/28/215052.html", "title": "Microblog posted at 28 Mar 2023 20:50:52", "url": "https://jasonrbriggs.com/micro/2023/03/28/215052.html", "content_text": "Dear Interwebs. Please don't put articles like this ([https://www.acc.org/About-ACC/Press-Releases/2023/02/22/21/35/Getting-Good-Sleep-Could-Add-Years-to-Your-Life](https://www.acc.org/About-ACC/Press-Releases/2023/02/22/21/35/Getting-Good-Sleep-Could-Add-Years-to-Your-Life)) in my news feed after 2 days of crappy sleeping due to the daylight saving change, and an entirely too early wake up call to drop my wife off at work...", "content_html": "Dear Interwebs. Please don't put articles like this (https://www.acc.org/About-ACC/Press-Releases/2023/02/22/21/35/Getting-Good-Sleep-Could-Add-Years-to-Your-Life) in my news feed after 2 days of crappy sleeping due to the daylight saving change, and an entirely too early wake up call to drop my wife off at work...
", "date_published": "2023-03-28T20:50:52+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/02/12/151719.html", "title": "Microblog posted at 12 Feb 2023 15:17:19", "url": "https://jasonrbriggs.com/micro/2023/02/12/151719.html", "content_text": "Hoo boy yeah:\n\n[workchronicles.com/nohellodotcom/](https://workchronicles.com/nohellodotcom/)", "content_html": "Hoo boy yeah:
\nworkchronicles.com/nohellodotcom/
", "date_published": "2023-02-12T15:17:19+00:00" }, { "id": "https://jasonrbriggs.com/micro/2023/01/21/201720.html", "title": "Microblog posted at 21 Jan 2023 20:17:20", "url": "https://jasonrbriggs.com/micro/2023/01/21/201720.html", "content_text": "[An update on duckduckgo search](https://jasonrbriggs.com/journal/2023/01/21/an-update-on-duckduckgo-search.html)", "content_html": "An update on duckduckgo search
", "date_published": "2023-01-21T20:17:20+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/12/18/155301.html", "title": "Microblog posted at 18 Dec 2022 15:53:01", "url": "https://jasonrbriggs.com/micro/2022/12/18/155301.html", "content_text": "[Salting with Spark](https://jasonrbriggs.com/journal/2022/12/17/salting-with-spark.html) (spark, pyspark, window functions and salting)", "content_html": "Salting with Spark (spark, pyspark, window functions and salting)
", "date_published": "2022-12-18T15:53:01+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/11/21/232313.html", "title": "Microblog posted at 21 Nov 2022 23:23:13", "url": "https://jasonrbriggs.com/micro/2022/11/21/232313.html", "content_text": "Bing hasn't indexed my site for 6 months or so now, which means that DuckDuckGo doesn't show results from my site either. From what I've been able to tell, there's absolutely no way to fix it short of a response from Microsoft (there's certainly not enough information to figure it out from their web developer tools) - of course I never received a response. Google, for all their faults, at least works. DDG need to fix their data sourcing because Bing really is the worst search engine...", "content_html": "Bing hasn't indexed my site for 6 months or so now, which means that DuckDuckGo doesn't show results from my site either. From what I've been able to tell, there's absolutely no way to fix it short of a response from Microsoft (there's certainly not enough information to figure it out from their web developer tools) - of course I never received a response. Google, for all their faults, at least works. DDG need to fix their data sourcing because Bing really is the worst search engine...
", "date_published": "2022-11-21T23:23:13+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/11/10/194918.html", "title": "Microblog posted at 10 Nov 2022 19:49:18", "url": "https://jasonrbriggs.com/micro/2022/11/10/194918.html", "content_text": "It would be brilliant if there was a REST-type service which supported the interactive parts of ActivityPub for static websites - my static generator could then interact with that to pull any new follower requests and update my inbox accordingly... the other option is I make my site slightly less static and build something myself... somewhat less enthusiastic about that idea though. [2/2]", "content_html": "It would be brilliant if there was a REST-type service which supported the interactive parts of ActivityPub for static websites - my static generator could then interact with that to pull any new follower requests and update my inbox accordingly... the other option is I make my site slightly less static and build something myself... somewhat less enthusiastic about that idea though. [2/2]
", "date_published": "2022-11-10T19:49:18+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/11/10/194150.html", "title": "Microblog posted at 10 Nov 2022 19:41:50", "url": "https://jasonrbriggs.com/micro/2022/11/10/194150.html", "content_text": "I've managed to get my personal site searchable in Mastodon ([mastodon.social/@jasonrbriggs@jasonrbriggs.com](https://mastodon.social/@jasonrbriggs@jasonrbriggs.com)) but, annoyingly, posts are not viewable (\"*Older posts from other servers are not displayed*\"). Haven't figured out how to get that working - my guess is it will only work for a follower, but unfortunately because it's a static site, there's no way for potential followers to be added to my inbox. [1/2]", "content_html": "I've managed to get my personal site searchable in Mastodon (mastodon.social/@jasonrbriggs@jasonrbriggs.com) but, annoyingly, posts are not viewable (\"Older posts from other servers are not displayed\"). Haven't figured out how to get that working - my guess is it will only work for a follower, but unfortunately because it's a static site, there's no way for potential followers to be added to my inbox. [1/2]
", "date_published": "2022-11-10T19:41:50+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/11/09/225614.html", "title": "Microblog posted at 09 Nov 2022 22:56:14", "url": "https://jasonrbriggs.com/micro/2022/11/09/225614.html", "content_text": "This is mind blowing: [My full statement regarding DOOM Eternal](https://medium.com/@mickgordon/my-full-statement-regarding-doom-eternal-5f98266b27ce)", "content_html": "This is mind blowing: My full statement regarding DOOM Eternal
", "date_published": "2022-11-09T22:56:14+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/08/06/103832.html", "title": "Microblog posted at 06 Aug 2022 09:38:32", "url": "https://jasonrbriggs.com/micro/2022/08/06/103832.html", "content_text": "[Leaving DuckDuckGo... sort of](https://jasonrbriggs.com/journal/2022/08/06/leaving-duckduckgo-sort-of.html)", "content_html": "", "date_published": "2022-08-06T09:38:32+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/07/30/095858.html", "title": "Microblog posted at 30 Jul 2022 08:58:58", "url": "https://jasonrbriggs.com/micro/2022/07/30/095858.html", "content_text": "For those who are interested, Python for Kids 2 has been completely rewritten as LaTeX... [Python for Kids 2 and LaTeX](https://jasonrbriggs.com/journal/2022/07/30/python-for-kids-2-and-latex.html)", "content_html": "For those who are interested, Python for Kids 2 has been completely rewritten as LaTeX... Python for Kids 2 and LaTeX
", "date_published": "2022-07-30T08:58:58+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/07/30/092256.html", "title": "Microblog posted at 30 Jul 2022 08:22:56", "url": "https://jasonrbriggs.com/micro/2022/07/30/092256.html", "content_text": "[RSS-IMAP](https://jasonrbriggs.com/journal/2022/07/29/rss-imap.html)", "content_html": "", "date_published": "2022-07-30T08:22:56+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/04/29/194256.html", "title": "Microblog posted at 29 Apr 2022 18:42:56", "url": "https://jasonrbriggs.com/micro/2022/04/29/194256.html", "content_text": "[Announcing: Python for Kids 2nd Edition](https://jasonrbriggs.com/journal/2022/04/29/announcing-python-for-kids-2nd-edition.html)", "content_html": "Announcing: Python for Kids 2nd Edition
", "date_published": "2022-04-29T18:42:56+00:00" }, { "id": "https://jasonrbriggs.com/micro/2022/04/22/223104.html", "title": "Microblog posted at 22 Apr 2022 21:31:04", "url": "https://jasonrbriggs.com/micro/2022/04/22/223104.html", "content_text": "[BBC micro:bit with Python for Kids](https://jasonrbriggs.com/journal/2022/04/18/bbc-microbit-with-python-for-kids.html)", "content_html": "BBC micro:bit with Python for Kids
", "date_published": "2022-04-22T21:31:04+00:00" }, { "id": "https://jasonrbriggs.com/micro/2021/11/16/223237.html", "title": "Microblog posted at 16 Nov 2021 22:32:37", "url": "https://jasonrbriggs.com/micro/2021/11/16/223237.html", "content_text": "[Em Học Python](https://jasonrbriggs.com/journal/2021/11/16/em-hoc-python.html)", "content_html": "", "date_published": "2021-11-16T22:32:37+00:00" }, { "id": "https://jasonrbriggs.com/micro/2021/07/04/090213.html", "title": "Microblog posted at 04 Jul 2021 09:02:13", "url": "https://jasonrbriggs.com/micro/2021/07/04/090213.html", "content_text": "[A Remarkable Silence: Media Blackout After Key Witness Against Assange Admits Lying](https://www.medialens.org/2021/a-remarkable-silence-media-blackout-after-key-witness-against-assange-admits-lying/)", "content_html": "A Remarkable Silence: Media Blackout After Key Witness Against Assange Admits Lying
", "date_published": "2021-07-04T09:02:13+01:00" }, { "id": "https://jasonrbriggs.com/micro/2021/03/19/231054.html", "title": "Microblog posted at 19 Mar 2021 23:10:54", "url": "https://jasonrbriggs.com/micro/2021/03/19/231054.html", "content_text": "[Spark-on-Pi](https://jasonrbriggs.com/journal/2021/03/19/spark-on-pi.html)", "content_html": "", "date_published": "2021-03-19T23:10:54+00:00" }, { "id": "https://jasonrbriggs.com/micro/2021/02/20/102001.html", "title": "Microblog posted at 20 Feb 2021 10:20:01", "url": "https://jasonrbriggs.com/micro/2021/02/20/102001.html", "content_text": "[The Bizarre Reaction To Facebook's Decision To Get Out Of The News Business In Australia](https://www.techdirt.com/articles/20210217/22383446265/bizarre-reaction-to-facebooks-decision-to-get-out-news-business-australia.shtml) (via [DaringFireball](https://daringfireball.net/linked/2021/02/18/masnick-facebook-australia)). Watched Ch4 News' biased coverage & BBC interviews with some idiotic UK politician, which just proved folk either don't get it, or have vested interests. I neither like nor use FB, but in this case they are right.", "content_html": "The Bizarre Reaction To Facebook's Decision To Get Out Of The News Business In Australia (via DaringFireball). Watched Ch4 News' biased coverage & BBC interviews with some idiotic UK politician, which just proved folk either don't get it, or have vested interests. I neither like nor use FB, but in this case they are right.
", "date_published": "2021-02-20T10:20:01+00:00" }, { "id": "https://jasonrbriggs.com/micro/2021/02/06/123137.html", "title": "Microblog posted at 06 Feb 2021 12:31:37", "url": "https://jasonrbriggs.com/micro/2021/02/06/123137.html", "content_text": "[Booting Raspberry Pi from External USB](https://jasonrbriggs.com/journal/2021/02/05/booting-raspberry-pi-from-external-usb.html)", "content_html": "Booting Raspberry Pi from External USB
", "date_published": "2021-02-06T12:31:37+00:00" }, { "id": "https://jasonrbriggs.com/micro/2021/01/30/154354.html", "title": "Microblog posted at 30 Jan 2021 15:43:54", "url": "https://jasonrbriggs.com/micro/2021/01/30/154354.html", "content_text": "[Breaking out of loops](https://jasonrbriggs.com/journal/2021/01/30/breaking-out-of-loops.html)", "content_html": "", "date_published": "2021-01-30T15:43:54+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/10/04/104919.html", "title": "Microblog posted at 04 Oct 2020 10:49:19", "url": "https://jasonrbriggs.com/micro/2020/10/04/104919.html", "content_text": "Tim Bray: [I Hate My MacBook](https://www.tbray.org/ongoing/When/202x/2020/10/02/I-Hate-My-MacBook) _\"if only it were faster. Is it possible I have a lemon?\"_. I don't think it's a lemon. I left the Mac world a few years ago now and moved to Linux. My wife inherited my old MacBook Pro and what I've noticed is that it seems to have gotten slower and slower over time, in a way I haven't seen outside of the Apple ecosystem. I recollect the same issue with the MacBook Black I had before that. Personally I think it's a design flaw. If I temporarily release my paranoid inner conspiracy theorist, I'd say it was a purposeful design flaw... ٩(ʘ益ʘ)۶ \nTim Bray: I Hate My MacBook \"if only it were faster. Is it possible I have a lemon?\". I don't think it's a lemon. I left the Mac world a few years ago now and moved to Linux. My wife inherited my old MacBook Pro and what I've noticed is that it seems to have gotten slower and slower over time, in a way I haven't seen outside of the Apple ecosystem. I recollect the same issue with the MacBook Black I had before that. Personally I think it's a design flaw. If I temporarily release my paranoid inner conspiracy theorist, I'd say it was a purposeful design flaw... ٩(ʘ益ʘ)۶
\n
\nMy recommendation would be a Dell XPS running Ubuntu (or another flavour - although I didn't have such a straightforward experience when I tried to use Arch).
I think critics of Epic taking on Apple, arguing that Epic should be applying the same logic to consoles, are ignoring the fact that Apple's profit margins are significantly higher on iPhones than what Sony makes on a PS4 by comparison. Nintendo profits on the Switch seem to be higher than a PS4, but not significantly so. Console makers have more justification for higher fees. Not an Epic/Fortnite fanboy (at all) but the story is a lot more complicated than they're making out...
", "date_published": "2020-08-22T17:38:38+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/07/25/200211.html", "title": "Microblog posted at 25 Jul 2020 20:02:11", "url": "https://jasonrbriggs.com/micro/2020/07/25/200211.html", "content_text": "[Tkinter colorchooser problems (revisited)](https://jasonrbriggs.com/journal/2020/07/23/tkinter-colorchooser-problems-(revisited).html)", "content_html": "Tkinter colorchooser problems (revisited)
", "date_published": "2020-07-25T20:02:11+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/07/05/171917.html", "title": "Microblog posted at 05 Jul 2020 17:19:17", "url": "https://jasonrbriggs.com/micro/2020/07/05/171917.html", "content_text": "[Top Few](https://jasonrbriggs.com/journal/2020/07/05/top-few.html)", "content_html": "", "date_published": "2020-07-05T17:19:17+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/05/30/231500.html", "title": "Microblog posted at 30 May 2020 23:15:00", "url": "https://jasonrbriggs.com/micro/2020/05/30/231500.html", "content_text": "[Problem with bouncing ball](https://jasonrbriggs.com/journal/2020/05/30/problem-with-bouncing-ball.html)", "content_html": "", "date_published": "2020-05-30T23:15:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/05/19/195732.html", "title": "Microblog posted at 19 May 2020 19:57:31", "url": "https://jasonrbriggs.com/micro/2020/05/19/195732.html", "content_text": "[![Learn you some Python](https://jasonrbriggs.com/micro/2020/05/19/learnyousomepython-small.jpg)](/micro/2020/05/19/learnyousomepython.jpg) \n[Humble Bundle - Learn you some Python](https://www.humblebundle.com/books/learn-you-some-python-no-starch-press-books)", "content_html": "
\nHumble Bundle - Learn you some Python
Ha! Re my previous post, I should've read the comments on the Register article:
\n\n", "date_published": "2020-05-05T18:18:38+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/05/05/180502.html", "title": "Microblog posted at 05 May 2020 18:05:02", "url": "https://jasonrbriggs.com/micro/2020/05/05/180502.html", "content_text": "[UK finds itself almost alone with centralized virus contact-tracing app that probably won't work well, asks for your location, may be illegal](https://www.theregister.co.uk/2020/05/05/uk_coronavirus_app/). Other than arrogance and stupidity, I don't know why the UK govt thinks they know better than the rest of the world. What am I saying... Brexit revisited... of course it's arrogance and stupidity.", "content_html": "Or, in the case of the British Government (and governments the world over): never attribute to malice what can adequately be explained by arrogance and paternalism.
\n
UK finds itself almost alone with centralized virus contact-tracing app that probably won't work well, asks for your location, may be illegal. Other than arrogance and stupidity, I don't know why the UK govt thinks they know better than the rest of the world. What am I saying... Brexit revisited... of course it's arrogance and stupidity.
", "date_published": "2020-05-05T18:05:02+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/05/03/173457.html", "title": "Microblog posted at 03 May 2020 17:11:57", "url": "https://jasonrbriggs.com/micro/2020/05/03/173457.html", "content_text": "[Online supermarket delivery in the UK needs to evolve](https://jasonrbriggs.com/u/obPAk03)", "content_html": "Online supermarket delivery in the UK needs to evolve
", "date_published": "2020-05-03T17:11:57+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/04/15/002057.html", "title": "Microblog posted at 15 Apr 2020 00:20:57", "url": "https://jasonrbriggs.com/micro/2020/04/15/002057.html", "content_text": "[Long and short dashes](https://jasonrbriggs.com/u/obPALGj)", "content_html": "", "date_published": "2020-04-15T00:20:57+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/04/13/090654.html", "title": "Microblog posted at 13 Apr 2020 09:06:54", "url": "https://jasonrbriggs.com/micro/2020/04/13/090654.html", "content_text": "Really nice review of Python for Kids on youtube here: [youtu.be/9Ep4UmJ6EZI](https://youtu.be/9Ep4UmJ6EZI).", "content_html": "Really nice review of Python for Kids on youtube here: youtu.be/9Ep4UmJ6EZI.
", "date_published": "2020-04-13T09:06:54+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/03/31/202311.html", "title": "Microblog posted at 31 Mar 2020 20:23:11", "url": "https://jasonrbriggs.com/micro/2020/03/31/202311.html", "content_text": "\"My city, in a stroke of brilliance, reduced the number of different tram lines and their frequency. Everything to make sure the otherwise reduced number of people on the streets is as tightly packed in public transport as possible. Big brain move\" [mastodon.social/@Gargron/103917675895934592](https://mastodon.social/@Gargron/103917675895934592). [@Gargron@mastodon.social](https://mastodon.social/@Gargron) Similar to what happened in London. Stupid is as stupid does...", "content_html": "\"My city, in a stroke of brilliance, reduced the number of different tram lines and their frequency. Everything to make sure the otherwise reduced number of people on the streets is as tightly packed in public transport as possible. Big brain move\" mastodon.social/@Gargron/103917675895934592. @Gargron@mastodon.social Similar to what happened in London. Stupid is as stupid does...
", "date_published": "2020-03-31T20:23:11+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/03/31/201919.html", "title": "Microblog posted at 31 Mar 2020 20:19:19", "url": "https://jasonrbriggs.com/micro/2020/03/31/201919.html", "content_text": "[\"UK considers virus-tracing app to ease lockdown\"](https://www.bbc.co.uk/news/technology-52095331). Well duh. [Finally](https://jasonrbriggs.com/micro/2020/03/17/225411.html)", "content_html": "\"UK considers virus-tracing app to ease lockdown\". Well duh. Finally
", "date_published": "2020-03-31T20:19:19+01:00" }, { "id": "https://jasonrbriggs.com/micro/2020/03/22/115624.html", "title": "Microblog posted at 22 Mar 2020 11:56:24", "url": "https://jasonrbriggs.com/micro/2020/03/22/115624.html", "content_text": "Singapore has an [interesting alternative](https://www.zdnet.com/article/singapore-introduces-contact-tracing-app-to-slow-coronavirus-spread/) on using mobiles for tracking (which I previously [posted](https://jasonrbriggs.com/micro/2020/03/17/225411.html) about).", "content_html": "Singapore has an interesting alternative on using mobiles for tracking (which I previously posted about).
", "date_published": "2020-03-22T11:56:24+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/03/17/225411.html", "title": "Microblog posted at 17 Mar 2020 22:54:11", "url": "https://jasonrbriggs.com/micro/2020/03/17/225411.html", "content_text": "This is an interesting idea: [mobile app for contact tracing can stop the epidemic](https://045.medsci.ox.ac.uk/mobile-app). Privacy advocates might not like it, but given the Oxford group recommend the app wouldn't need to be compulsory, perhaps if enough people decide it's worth doing *something* to fight the virus rather than nothing...?", "content_html": "This is an interesting idea: mobile app for contact tracing can stop the epidemic. Privacy advocates might not like it, but given the Oxford group recommend the app wouldn't need to be compulsory, perhaps if enough people decide it's worth doing something to fight the virus rather than nothing...?
", "date_published": "2020-03-17T22:54:11+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/03/16/195202.html", "title": "Microblog posted at 16 Mar 2020 19:52:02", "url": "https://jasonrbriggs.com/micro/2020/03/16/195202.html", "content_text": "Python for Kids is a part of the [Coding Starter Kit Humble Bundle](https://www.humblebundle.com/books/coding-starter-kit-no-starch-press-books).", "content_html": "Python for Kids is a part of the Coding Starter Kit Humble Bundle.
", "date_published": "2020-03-16T19:52:02+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/02/22/095208.html", "title": "Microblog posted at 22 Feb 2020 09:52:08", "url": "https://jasonrbriggs.com/micro/2020/02/22/095208.html", "content_text": "Amazon. Pfft. Who's surprised by [this](https://petapixel.com/2020/02/21/amazon-let-a-fraudster-keep-my-sony-a7r-iv-and-refunded-him-2900/)?", "content_html": "Amazon. Pfft. Who's surprised by this?
", "date_published": "2020-02-22T09:52:08+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/02/01/173749.html", "title": "Microblog posted at 01 Feb 2020 17:37:49", "url": "https://jasonrbriggs.com/micro/2020/02/01/173749.html", "content_text": "[It's time for engineers to champion repair](https://spectrum.ieee.org/tech-talk/at-work/education/engineering-a-repairable-world)", "content_html": "It's time for engineers to champion repair
", "date_published": "2020-02-01T17:37:49+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/02/01/091913.html", "title": "Microblog posted at 01 Feb 2020 09:19:13", "url": "https://jasonrbriggs.com/micro/2020/02/01/091913.html", "content_text": "[UN special rapporteur on torture on his investigation into the case of Assange](https://www.republik.ch/2020/01/31/nils-melzer-about-wikileaks-founder-julian-assange)", "content_html": "UN special rapporteur on torture on his investigation into the case of Assange
", "date_published": "2020-02-01T09:19:13+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/01/22/193112.html", "title": "Microblog posted at 22 Jan 2020 19:31:12", "url": "https://jasonrbriggs.com/micro/2020/01/22/193112.html", "content_text": "Via Nat T's [Four Short Links](https://www.oreilly.com/radar/four-short-links-10-january-2020/) and [Boing Boing](https://boingboing.net/2020/01/08/rip-open-web-platform.html), who saw this coming: \"[The End of Indie Web Browsers](https://blog.samuelmaddock.com/posts/the-end-of-indie-web-browsers/)\"? Answer: [e ](https://www.eff.org/deeplinks/2017/07/amid-unprecedented-controversy-w3c-greenlights-drm-web)[v ](https://news.softpedia.com/news/DRM-for-HTML-Proposal-Discussed-by-W3C-the-Bad-Idea-that-Won-t-Go-Away-329249.shtml)[e ](https://www.bleepingcomputer.com/news/technology/w3c-brazenly-ignores-all-critics-and-approves-browser-drm-standard/)[r ](https://www.techdirt.com/articles/20170918/16322838234/eff-resigns-w3c-after-drm-html-is-approved-secret-vote.shtml)[y ](https://creativecommons.org/2013/04/11/drm-in-html5-is-a-bad-idea/)[o ](https://blog.archive.org/2017/04/18/drm-for-the-web-is-a-bad-idea/)[n ](https://www.theinquirer.net/inquirer/news/3013476/w3c-passes-new-drm-standard-and-a-lot-of-its-members-arent-happy)[e ](https://www.techdirt.com/articles/20170403/23575537077/unesco-says-adding-drm-to-html-is-very-bad-idea.shtml)", "content_html": "Via Nat T's Four Short Links and Boing Boing, who saw this coming: \"The End of Indie Web Browsers\"? Answer: e v e r y o n e
", "date_published": "2020-01-22T19:31:12+00:00" }, { "id": "https://jasonrbriggs.com/micro/2020/01/18/162558.html", "title": "Microblog posted at 18 Jan 2020 16:25:58", "url": "https://jasonrbriggs.com/micro/2020/01/18/162558.html", "content_text": "[ICANN corruption](https://jasonrbriggs.com/journal/2020/01/17/icann-corruption.html)", "content_html": "", "date_published": "2020-01-18T16:25:58+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/12/30/101055.html", "title": "Microblog posted at 30 Dec 2019 10:10:55", "url": "https://jasonrbriggs.com/micro/2019/12/30/101055.html", "content_text": "As per [python3statement.org](http://python3statement.org/), [stomp.py](https://github.com/jasonrbriggs/stomp.py) is officially ending support for Python2 as of Jan. Surprisingly more effort than anticipated, but the PR for version 4.2.0 is finally prepped and ready to go: [stomp.py/pull/266](https://github.com/jasonrbriggs/stomp.py/pull/266). The [changelog](https://github.com/jasonrbriggs/stomp.py/blob/9ff1fbc4ff08f43b51b04b39872f884e47d39803/CHANGELOG) has more detail on what's being updated in addition to Py2 backwards-compability removal.", "content_html": "As per python3statement.org, stomp.py is officially ending support for Python2 as of Jan. Surprisingly more effort than anticipated, but the PR for version 4.2.0 is finally prepped and ready to go: stomp.py/pull/266. The changelog has more detail on what's being updated in addition to Py2 backwards-compability removal.
", "date_published": "2019-12-30T10:10:55+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/12/23/102920.html", "title": "Microblog posted at 23 Dec 2019 10:29:20", "url": "https://jasonrbriggs.com/micro/2019/12/23/102920.html", "content_text": "Python [coverage](https://coverage.readthedocs.io/en/coverage-5.0/) reporting has been doing my head in for days. Methods with full coverage still showed the method signature line itself as uncovered. Lines which I know are covered (and can see the unittest working) still showed as red. Turns out I'd left an import of the module-under-test in place before starting coverage itself. Fix that and suddenly my code coverage goes from <50% to a more respectable 80%. Sometimes the solution to a problem **is** as simple as moving a line of code...", "content_html": "Python coverage reporting has been doing my head in for days. Methods with full coverage still showed the method signature line itself as uncovered. Lines which I know are covered (and can see the unittest working) still showed as red. Turns out I'd left an import of the module-under-test in place before starting coverage itself. Fix that and suddenly my code coverage goes from <50% to a more respectable 80%. Sometimes the solution to a problem is as simple as moving a line of code...
", "date_published": "2019-12-23T10:29:20+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/12/15/191520.html", "title": "Microblog posted at 15 Dec 2019 19:15:20", "url": "https://jasonrbriggs.com/micro/2019/12/15/191520.html", "content_text": "Been trying to get ipv6 working with docker for days with no luck. Everything I read (for example: [ungleich.ch/u/blog/how-to-enable-ipv6-in-docker](https://ungleich.ch/u/blog/how-to-enable-ipv6-in-docker/)) seems to suggest it's simple, yet my containers still end up with ipv4 only. Finally found the problem between my keyboard and my chair - editing /etc/docker/daemon.json doesn't help if your docker daemon is running with --config-file=/var/snap/docker/423/config/daemon.json... :old_man:", "content_html": "Been trying to get ipv6 working with docker for days with no luck. Everything I read (for example: ungleich.ch/u/blog/how-to-enable-ipv6-in-docker) seems to suggest it's simple, yet my containers still end up with ipv4 only. Finally found the problem between my keyboard and my chair - editing /etc/docker/daemon.json doesn't help if your docker daemon is running with --config-file=/var/snap/docker/423/config/daemon.json... 👴
", "date_published": "2019-12-15T19:15:20+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/11/29/192020.html", "title": "Microblog posted at 29 Nov 2019 19:20:20", "url": "https://jasonrbriggs.com/micro/2019/11/29/192020.html", "content_text": "These [idiots](https://en.wikipedia.org/wiki/Conservative_Party_(UK)) have [lost touch with reality](https://www.heraldscotland.com/news/18067964.tory-source-threat-channel-4-licence-boris-johnson-replaced-ice-sculpture-debate-stunt/) frankly.", "content_html": "These idiots have lost touch with reality frankly.
", "date_published": "2019-11-29T19:20:20+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/11/03/092518.html", "title": "Microblog posted at 03 Nov 2019 09:25:18", "url": "https://jasonrbriggs.com/micro/2019/11/03/092518.html", "content_text": "RT [@AllBlacks](https://twitter.com/AllBlacks) Congratulations to [@Springboks](https://twitter.com/Springboks) on winning the 2019 Rugby World Cup. Enjoy every moment. #RWC2019 [twitter.com/AllBlacks/status/1190592577671557121](https://twitter.com/AllBlacks/status/1190592577671557121)", "content_html": "RT @AllBlacks Congratulations to @Springboks on winning the 2019 Rugby World Cup. Enjoy every moment. #RWC2019 twitter.com/AllBlacks/status/1190592577671557121
", "date_published": "2019-11-03T09:25:18+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/11/02/125748.html", "title": "Microblog posted at 02 Nov 2019 12:57:48", "url": "https://jasonrbriggs.com/micro/2019/11/02/125748.html", "content_text": "[Great game](https://www.nzherald.co.nz/sport/news/article.cfm?c_id=4&objectid=12281870)", "content_html": "", "date_published": "2019-11-02T12:57:48+00:00" }, { "id": "https://jasonrbriggs.com/micro/2019/10/26/112815.html", "title": "Microblog posted at 26 Oct 2019 11:28:15", "url": "https://jasonrbriggs.com/micro/2019/10/26/112815.html", "content_text": "[Gah!](https://www.nzherald.co.nz/sport/news/article.cfm?c_id=4&objectid=12279985)", "content_html": "", "date_published": "2019-10-26T11:28:15+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/10/14/214159.html", "title": "Microblog posted at 14 Oct 2019 21:41:59", "url": "https://jasonrbriggs.com/micro/2019/10/14/214159.html", "content_text": "[Beware Counterfeit No Starch Books from Amazon!](https://dev.to/codemouse92/beware-counterfeit-no-starch-books-2232). Kind of annoying given this is Amazon itself, not a third party. So their supply chain controls are simply beyond inadequate, or they just have too much money and power to care.", "content_html": "Beware Counterfeit No Starch Books from Amazon!. Kind of annoying given this is Amazon itself, not a third party. So their supply chain controls are simply beyond inadequate, or they just have too much money and power to care.
", "date_published": "2019-10-14T21:41:59+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/10/06/091253.html", "title": "Microblog posted at 06 Oct 2019 09:12:53", "url": "https://jasonrbriggs.com/micro/2019/10/06/091253.html", "content_text": "The game started off messy, but that [Perenara try](https://www.nzherald.co.nz/sport/news/article.cfm?c_id=4&objectid=12274105) was just a thing of beauty...", "content_html": "The game started off messy, but that Perenara try was just a thing of beauty...
", "date_published": "2019-10-06T09:12:53+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/10/01/194555.html", "title": "Microblog posted at 01 Oct 2019 19:45:55", "url": "https://jasonrbriggs.com/micro/2019/10/01/194555.html", "content_text": "Eleven supreme court justices with decades of experience in UK Law find that prorogation was unlawful. Rees-Mogg, with a History degree (!) believes they're wrong. They obviously don't teach critical thinking at Oxford, if you're reading History...?", "content_html": "Eleven supreme court justices with decades of experience in UK Law find that prorogation was unlawful. Rees-Mogg, with a History degree (!) believes they're wrong. They obviously don't teach critical thinking at Oxford, if you're reading History...?
", "date_published": "2019-10-01T19:45:55+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/09/28/104304.html", "title": "Microblog posted at 28 Sep 2019 10:43:04", "url": "https://jasonrbriggs.com/micro/2019/09/28/104304.html", "content_text": "[Disco Dingo](http://releases.ubuntu.com/19.04/) one day in... so far, so good. [Dash to dock](https://extensions.gnome.org/extension/307/dash-to-dock/) seemed to go pear-shaped to start with - even after upgrading it - but a reboot fixed that luckily. New icons are great, UI looks a bit cleaner/fresher. Really liking the notification icons (e.g. number of new mails) in the dock (users of other operating systems, who have had this for ages, can start laughing now).", "content_html": "Disco Dingo one day in... so far, so good. Dash to dock seemed to go pear-shaped to start with - even after upgrading it - but a reboot fixed that luckily. New icons are great, UI looks a bit cleaner/fresher. Really liking the notification icons (e.g. number of new mails) in the dock (users of other operating systems, who have had this for ages, can start laughing now).
", "date_published": "2019-09-28T10:43:04+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/09/22/112250.html", "title": "Microblog posted at 22 Sep 2019 11:22:50", "url": "https://jasonrbriggs.com/micro/2019/09/22/112250.html", "content_text": "Problems with restarting the game: [jasonrbriggs.com/u/obNSPbh](https://jasonrbriggs.com/u/obNSPbh)", "content_html": "Problems with restarting the game: jasonrbriggs.com/u/obNSPbh
", "date_published": "2019-09-22T11:22:50+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/09/16/183140.html", "title": "Microblog posted at 16 Sep 2019 18:31:40", "url": "https://jasonrbriggs.com/micro/2019/09/16/183140.html", "content_text": "RT [@MarkRuffalo](https://twitter.com/MarkRuffalo) Boris Johnson forgets that the Hulk only fights for the good of the whole. Mad and strong can also be dense and destructive. The Hulk works best when he is in unison with a team, and is a disaster when he is alone. Plus...he’s always got Dr. Banner with science and reason. [twitter.com/MarkRuffalo/status/1173273612075376641](https://twitter.com/MarkRuffalo/status/1173273612075376641) :thumbs_up:", "content_html": "RT @MarkRuffalo Boris Johnson forgets that the Hulk only fights for the good of the whole. Mad and strong can also be dense and destructive. The Hulk works best when he is in unison with a team, and is a disaster when he is alone. Plus...he’s always got Dr. Banner with science and reason. twitter.com/MarkRuffalo/status/1173273612075376641 👍
", "date_published": "2019-09-16T18:31:40+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/09/08/001108.html", "title": "Microblog posted at 08 Sep 2019 00:11:08", "url": "https://jasonrbriggs.com/micro/2019/09/08/001108.html", "content_text": "IDLE3 on Ubuntu: [jasonrbriggs.com/u/obNSKSi](https://jasonrbriggs.com/u/obNSKSi)", "content_html": "IDLE3 on Ubuntu: jasonrbriggs.com/u/obNSKSi
", "date_published": "2019-09-08T00:11:08+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/09/04/231410.html", "title": "Microblog posted at 04 Sep 2019 23:14:10", "url": "https://jasonrbriggs.com/micro/2019/09/04/231410.html", "content_text": "https://www.rorystewart.co.uk/no-deal-2/ :thumbs_up:https://www.rorystewart.co.uk/no-deal-2/ 👍
\n(i.e. The Johnson's, Rees-Mogg's, etc of this world are complete morons)
Watching Gove on @MarrShow, and have never felt such an urge to punch the TV screen. Just shut up with the lies and stretched-truths.
", "date_published": "2019-09-01T09:56:30+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/29/235636.html", "title": "Microblog posted at 29 Aug 2019 23:56:36", "url": "https://jasonrbriggs.com/micro/2019/08/29/235636.html", "content_text": "Minor update to [Trouble with Turtles](https://jasonrbriggs.com/journal/2018/02/11/trouble-with-turtles.html).", "content_html": "Minor update to Trouble with Turtles.
", "date_published": "2019-08-29T23:56:36+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/29/182758.html", "title": "Microblog posted at 29 Aug 2019 18:27:58", "url": "https://jasonrbriggs.com/micro/2019/08/29/182758.html", "content_text": "[Linux on Dex](https://www.linuxondex.com/) is pretty cool. Being able to run a full desktop environment in a [device](https://en.wikipedia.org/wiki/Samsung_Galaxy_S9) that fits in your pocket is something I dreamed about, 25 or so years ago when I was a backpacker. [This](https://en.wikipedia.org/wiki/Psion_Series_3) is the best I could do at the time. Actually, I have fond memories of the Psion Series 3, but it was hardly the sort of device you could actually do development work on...\n\nI'm living in the future!", "content_html": "Linux on Dex is pretty cool. Being able to run a full desktop environment in a device that fits in your pocket is something I dreamed about, 25 or so years ago when I was a backpacker. This is the best I could do at the time. Actually, I have fond memories of the Psion Series 3, but it was hardly the sort of device you could actually do development work on...
\nI'm living in the future!
", "date_published": "2019-08-29T18:27:58+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/25/172853.html", "title": "Microblog posted at 25 Aug 2019 17:28:53", "url": "https://jasonrbriggs.com/micro/2019/08/25/172853.html", "content_text": "Test post: testing if adding u-url fixes federation issue with fed.brid.gy.", "content_html": "Test post: testing if adding u-url fixes federation issue with fed.brid.gy.
", "date_published": "2019-08-25T17:28:53+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/17/101611.html", "title": "Microblog posted at 17 Aug 2019 10:16:11", "url": "https://jasonrbriggs.com/micro/2019/08/17/101611.html", "content_text": "\"So here's a list of companies supporting Trump's re-election: \n- Bang\n- inn n out \n- chick fil a\n- Taco Bell\n- McDonald’s \n- Wendy's \n- KFC\n- Pizza Hut\n- Olive Garden \n- Waffle House \n- IHOP\n- Carl's Jr.\n\nSo if you see me starting to get thinner and toned don't ask me why.\" twitter.com/BillyBobSanderz/status/1159469980435374080 :thumbs_up:", "content_html": "\"So here's a list of companies supporting Trump's re-election: \n- Bang\n- inn n out \n- chick fil a\n- Taco Bell\n- McDonald’s \n- Wendy's \n- KFC\n- Pizza Hut\n- Olive Garden \n- Waffle House \n- IHOP\n- Carl's Jr.
\nSo if you see me starting to get thinner and toned don't ask me why.\" twitter.com/BillyBobSanderz/status/1159469980435374080 👍
", "date_published": "2019-08-17T10:16:11+07:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/12/195738.html", "title": "Microblog posted at 12 Aug 2019 19:57:38", "url": "https://jasonrbriggs.com/micro/2019/08/12/195738.html", "content_text": "First up, a url followed by a thumbs up emoji (e.g. colon thumbs_up colon) gets auto-converted into an link (a href) with a microformat class of 'u-like-of'. So, assuming I've hooked up my site properly to [fed.brid.gy](https://fed.brid.gy/), those should wind up being magically forwarded on to the fediverse (todo: I think I still need to send fed.brid.gy a webmention to kick that process off...) (2/2)", "content_html": "First up, a url followed by a thumbs up emoji (e.g. colon thumbs_up colon) gets auto-converted into an link (a href) with a microformat class of 'u-like-of'. So, assuming I've hooked up my site properly to fed.brid.gy, those should wind up being magically forwarded on to the fediverse (todo: I think I still need to send fed.brid.gy a webmention to kick that process off...) (2/2)
", "date_published": "2019-08-12T19:57:38+07:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/12/195048.html", "title": "Microblog posted at 12 Aug 2019 19:50:48", "url": "https://jasonrbriggs.com/micro/2019/08/12/195048.html", "content_text": "After much reflection, I finally decided to rewrite my static site generator in [Nim](https://nim-lang.org), greatly simplifying things in the process - along with the name: SiteBaker now just becomes [Baker](https://github.com/jasonrbriggs/baker). Now comes the task of adding features I was too lazy to add before. (1/2)", "content_html": "After much reflection, I finally decided to rewrite my static site generator in Nim, greatly simplifying things in the process - along with the name: SiteBaker now just becomes Baker. Now comes the task of adding features I was too lazy to add before. (1/2)
", "date_published": "2019-08-12T19:50:48+07:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/07/193521.html", "title": "Microblog posted at 07 Aug 2019 19:35:21", "url": "https://jasonrbriggs.com/micro/2019/08/07/193521.html", "content_text": "Test post: just testing out the rss->activitypub converter at [tinysubversions.com](https://bots.tinysubversions.com/)\n", "content_html": "Test post: just testing out the rss->activitypub converter at tinysubversions.com
", "date_published": "2019-08-07T19:35:21+12:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/03/093137.html", "title": "Microblog posted at 03 Aug 2019 09:31:37", "url": "https://jasonrbriggs.com/micro/2019/08/03/093137.html", "content_text": "Not the normal knock-off: [jasonrbriggs.com/u/obNRqGn](https://jasonrbriggs.com/u/obNRqGn)", "content_html": "Not the normal knock-off: jasonrbriggs.com/u/obNRqGn
", "date_published": "2019-08-03T09:31:37+12:00" }, { "id": "https://jasonrbriggs.com/micro/2019/08/01/163004.html", "title": "Microblog posted at 01 Aug 2019 16:30:04", "url": "https://jasonrbriggs.com/micro/2019/08/01/163004.html", "content_text": "\"I’m a modest Stylite, but I must tell you I have solved Brexit.\" https://twitter.com/Sime0nStylites/status/1092343448483651589 :thumbs_up: \n \nAwesome.\n", "content_html": "\"I’m a modest Stylite, but I must tell you I have solved Brexit.\" https://twitter.com/Sime0nStylites/status/1092343448483651589 👍 \n \nAwesome.
", "date_published": "2019-08-01T16:30:04+12:00" }, { "id": "https://jasonrbriggs.com/micro/2019/07/22/152240.html", "title": "Microblog posted at 22 Jul 2019 15:22:40", "url": "https://jasonrbriggs.com/micro/2019/07/22/152240.html", "content_text": "", "content_html": "", "date_published": "2019-07-22T15:22:40+12:00" }, { "id": "https://jasonrbriggs.com/micro/2019/07/10/212254.html", "title": "Microblog posted at 10 Jul 2019 21:22:54", "url": "https://jasonrbriggs.com/micro/2019/07/10/212254.html", "content_text": ":link: [mattstoller.substack.com/p/the-slow-death-of-hollywood](https://mattstoller.substack.com/p/the-slow-death-of-hollywood)", "content_html": "🔗 mattstoller.substack.com/p/the-slow-death-of-hollywood
", "date_published": "2019-07-10T21:22:54+01:00" }, { "id": "https://jasonrbriggs.com/micro/2019/06/14/235500.html", "title": "Microblog posted at 14 Jun 2019 11:56:00", "url": "https://jasonrbriggs.com/micro/2019/06/14/235500.html", "content_text": "[@higgidy@twitter](https://twitter.com/higgidy) Nice pies but I don't understand the sheer amount of pointless plastic:\n\n![pointless-plastic](https://jasonrbriggs.com/micro/2019/06/14/pointless-plastic-small.jpg)\n\nWhy isn't it a tin-foil tray and then a plain cardboard box with the picture of the pie on the front, rather than a window?? In fact, why is there a tray at all??\n\nNuts.", "content_html": "@higgidy@twitter Nice pies but I don't understand the sheer amount of pointless plastic:
\n\nWhy isn't it a tin-foil tray and then a plain cardboard box with the picture of the pie on the front, rather than a window?? In fact, why is there a tray at all??
\nNuts.
", "date_published": "2019-06-14T11:56:00+00:00" }, { "id": "https://jasonrbriggs.com/micro/2018/11/11/112358.html", "title": "Microblog posted at 11 Nov 2018 11:23:59", "url": "https://jasonrbriggs.com/micro/2018/11/11/112358.html", "content_text": "I'll take luck over good in a pinch... [https://www.nzherald.co.nz/sport/news/...](https://www.nzherald.co.nz/sport/news/article.cfm?c_id=4&objectid=12158158)", "content_html": "I'll take luck over good in a pinch... https://www.nzherald.co.nz/sport/news/...
", "date_published": "2018-11-11T11:23:59+00:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/29/175327.html", "title": "Microblog posted at 29 Sep 2018 17:53:31", "url": "https://jasonrbriggs.com/micro/2018/09/29/175327.html", "content_text": "Trouble with GIMP: [jasonrbriggs.com/u/obMf7mm](https://jasonrbriggs.com/u/obMf7mm)", "content_html": "Trouble with GIMP: jasonrbriggs.com/u/obMf7mm
", "date_published": "2018-09-29T17:53:31+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/23/113405.html", "title": "Microblog posted at 23 Sep 2018 11:34:08", "url": "https://jasonrbriggs.com/micro/2018/09/23/113405.html", "content_text": "Modified IDLE: [jasonrbriggs.com/u/obMf66i](https://jasonrbriggs.com/u/obMf66i)", "content_html": "Modified IDLE: jasonrbriggs.com/u/obMf66i
", "date_published": "2018-09-23T11:34:08+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/22/100619.html", "title": "Microblog posted at 22 Sep 2018 10:06:41", "url": "https://jasonrbriggs.com/micro/2018/09/22/100619.html", "content_text": "Managed to reduce the macbook partition in chunks of 5GB at a time, down to the point I could fit Ubuntu - after that, surprisingly easy to install (using [rEFInd](http://www.rodsbooks.com/refind/) is critical I think). Hidedously slow to startup afterwards... although now I don't know if that's because I've got used to a faster machine with SSD", "content_html": "Managed to reduce the macbook partition in chunks of 5GB at a time, down to the point I could fit Ubuntu - after that, surprisingly easy to install (using rEFInd is critical I think). Hidedously slow to startup afterwards... although now I don't know if that's because I've got used to a faster machine with SSD
", "date_published": "2018-09-22T10:06:41+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/20/192652.html", "title": "Microblog posted at 20 Sep 2018 19:27:06", "url": "https://jasonrbriggs.com/micro/2018/09/20/192652.html", "content_text": "Out of the blue, just remembered one place I now quite miss visiting (from when we used to live in Auckland): [Brewer's Coop](http://www.brewerscoop.co.nz). I haven't brewed my own beer in over 10 years - I don't think I've even seen a home brew supplier since moving to England.", "content_html": "Out of the blue, just remembered one place I now quite miss visiting (from when we used to live in Auckland): Brewer's Coop. I haven't brewed my own beer in over 10 years - I don't think I've even seen a home brew supplier since moving to England.
", "date_published": "2018-09-20T19:27:06+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/19/203321.html", "title": "Microblog posted at 19 Sep 2018 20:34:25", "url": "https://jasonrbriggs.com/micro/2018/09/19/203321.html", "content_text": "Going to try installing ubuntu on an old macbook... so far so miserable. Haven't even been able to resize the boot partition so far.", "content_html": "Going to try installing ubuntu on an old macbook... so far so miserable. Haven't even been able to resize the boot partition so far.
", "date_published": "2018-09-19T20:34:25+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/18/android.html", "title": "Microblog posted at 18 Sep 2018 22:55:49", "url": "https://jasonrbriggs.com/micro/2018/09/18/android.html", "content_text": "One thing they don't tell you about switching from iOS to Android is the proliferation of non-obvious notifications. My S9 buzzes a lot more than I remember the iPhone doing, and half the time I have no idea why...", "content_html": "One thing they don't tell you about switching from iOS to Android is the proliferation of non-obvious notifications. My S9 buzzes a lot more than I remember the iPhone doing, and half the time I have no idea why...
", "date_published": "2018-09-18T22:55:49+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/17/brexit.html", "title": "Microblog posted at 17 Sep 2018 18:24:14", "url": "https://jasonrbriggs.com/micro/2018/09/17/brexit.html", "content_text": "Hearing the [B word](https://en.wikipedia.org/wiki/Brexit) is literally becoming like fingernails on a blackboard for me", "content_html": "Hearing the B word is literally becoming like fingernails on a blackboard for me
", "date_published": "2018-09-17T18:24:14+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/16/cooking.html", "title": "Microblog posted at 16 Sep 2018 10:17:53", "url": "https://jasonrbriggs.com/micro/2018/09/16/cooking.html", "content_text": "I'm not much of a cook, but occasionally I make something that turns out like the pictures. Made [cauliflower tacos](https://ordinaryvegan.net/vegan-cauliflower-tacos/) last night... sounds weird, surprisingly good (although used egg because I'm not a vegan).", "content_html": "I'm not much of a cook, but occasionally I make something that turns out like the pictures. Made cauliflower tacos last night... sounds weird, surprisingly good (although used egg because I'm not a vegan).
", "date_published": "2018-09-16T10:17:53+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/15/well-dang.html", "title": "Microblog posted at 15 Sep 2018 12:13:45", "url": "https://jasonrbriggs.com/micro/2018/09/15/well-dang.html", "content_text": "Well, dang... [Bok Shock](https://www.nzherald.co.nz/sport/news/article.cfm?c_id=4&objectid=12125884)", "content_html": "Well, dang... Bok Shock
", "date_published": "2018-09-15T12:13:45+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/14/micro-blogging-part-2.html", "title": "Microblog posted at 14 Sep 2018 20:56:20", "url": "https://jasonrbriggs.com/micro/2018/09/14/micro-blogging-part-2.html", "content_text": "Having second thoughts about [fixing](https://jasonrbriggs.com/micro/2018/09/08/micro-blogging.html) my static generator code. Now wondering if it requires starting again... or something even more drastic...", "content_html": "Having second thoughts about fixing my static generator code. Now wondering if it requires starting again... or something even more drastic...
", "date_published": "2018-09-14T20:56:20+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/13/iphone-xs.html", "title": "Microblog posted at 13 Sep 2018 19:31:03", "url": "https://jasonrbriggs.com/micro/2018/09/13/iphone-xs.html", "content_text": "iPhone Xs with 512GB of RAM: £1349. Samsung S9 with 64GB of RAM and a 400GB microSD card: £632. I mean, yes the iPhone X range look nice, but yikes!", "content_html": "iPhone Xs with 512GB of RAM: £1349. Samsung S9 with 64GB of RAM and a 400GB microSD card: £632. I mean, yes the iPhone X range look nice, but yikes!
", "date_published": "2018-09-13T19:31:03+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/12/rsi.html", "title": "Microblog posted at 12 Sep 2018 19:32:22", "url": "https://jasonrbriggs.com/micro/2018/09/12/rsi.html", "content_text": "[@justindirose](https://micro.blog/justindirose) Are you using an RSI break reminder? I had RSI years ago & the only thing that worked 4 me was taking a break every 4-5 mins, with appropriate exercises. Over time it got to the point that I didn't need the reminder any more & (touch wood) haven't had any problems in some time", "content_html": "@justindirose Are you using an RSI break reminder? I had RSI years ago & the only thing that worked 4 me was taking a break every 4-5 mins, with appropriate exercises. Over time it got to the point that I didn't need the reminder any more & (touch wood) haven't had any problems in some time
", "date_published": "2018-09-12T19:32:22+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/11/slow-refresh.html", "title": "Microblog posted at 11 Sep 2018 22:27:59", "url": "https://jasonrbriggs.com/micro/2018/09/11/slow-refresh.html", "content_text": "Is anyone else noticing there are periods (10+ hours) when [micro.blog/discover](https://micro.blog/discover) doesn't refresh?", "content_html": "Is anyone else noticing there are periods (10+ hours) when micro.blog/discover doesn't refresh?
", "date_published": "2018-09-11T22:27:59+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/10/winter-coming.html", "title": "Microblog posted at 10 Sep 2018 23:55:13", "url": "https://jasonrbriggs.com/micro/2018/09/10/winter-coming.html", "content_text": "How can you tell winter (or at least autumn) is coming? Aragog's friends decide they like it better inside the house than out... 😦", "content_html": "How can you tell winter (or at least autumn) is coming? Aragog's friends decide they like it better inside the house than out... 😦
", "date_published": "2018-09-10T23:55:13+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/10/samsung-s9-1.html", "title": "Microblog posted at 10 Sep 2018 23:48:21", "url": "https://jasonrbriggs.com/micro/2018/09/10/samsung-s9-1.html", "content_text": "One thing I couldn't find about Samsung Dex Pad, when I was researching whether to bother getting one, was if it works with ether-over-USB (there's no ethernet port on the latest version) Found one reference that it *should* work, so decided to risk it. Turns out, yes it does - I bought a TeckNet adapter and that's working fine. At least, I'm not getting the horrific wifi slowdown in the one patchy/dead dead spot in the house... coincidentally where I decided to put my desk 😞", "content_html": "One thing I couldn't find about Samsung Dex Pad, when I was researching whether to bother getting one, was if it works with ether-over-USB (there's no ethernet port on the latest version) Found one reference that it should work, so decided to risk it. Turns out, yes it does - I bought a TeckNet adapter and that's working fine. At least, I'm not getting the horrific wifi slowdown in the one patchy/dead dead spot in the house... coincidentally where I decided to put my desk 😞
", "date_published": "2018-09-10T23:48:21+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/09/micro-blog.html", "title": "Microblog posted at 09 Sep 2018 23:58:56", "url": "https://jasonrbriggs.com/micro/2018/09/09/micro-blog.html", "content_text": "[@help](https://micro.blog/help) Something weird I've noticed about micro.blog reading my external RSS feed -- it's reading the title, not the description, and titles should not contain markup according to the w3 validator. A few days ago it seemed to be correctly rendering links anyway, but today I notice that it's no longer working. Interestingly in my timeline I see posts where the links are rendering and where they aren't. Odd no?", "content_html": "@help Something weird I've noticed about micro.blog reading my external RSS feed -- it's reading the title, not the description, and titles should not contain markup according to the w3 validator. A few days ago it seemed to be correctly rendering links anyway, but today I notice that it's no longer working. Interestingly in my timeline I see posts where the links are rendering and where they aren't. Odd no?
", "date_published": "2018-09-09T23:58:56+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/09/mastodon.html", "title": "Microblog posted at 09 Sep 2018 23:41:19", "url": "https://jasonrbriggs.com/micro/2018/09/09/mastodon.html", "content_text": "Mastodon account deleted. Oooh... I've gone full [indieweb](https://indieweb.org/)...", "content_html": "Mastodon account deleted. Oooh... I've gone full indieweb...
", "date_published": "2018-09-09T23:41:19+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/08/micro-blogging.html", "title": "Microblog posted at 08 Sep 2018 17:59:24", "url": "https://jasonrbriggs.com/micro/2018/09/08/micro-blogging.html", "content_text": "So static-site micro-blogging from the commandline is working fine. Next on the todo list, fix the mess I've now made of the code (because of course there is no reason anyone would want more than one RSS feed on their site...), and then add a way to post entries from the web (because why would anyone want a web interface for a static site...)", "content_html": "So static-site micro-blogging from the commandline is working fine. Next on the todo list, fix the mess I've now made of the code (because of course there is no reason anyone would want more than one RSS feed on their site...), and then add a way to post entries from the web (because why would anyone want a web interface for a static site...)
", "date_published": "2018-09-08T17:59:24+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/07/just-testing.html", "title": "Microblog posted at 07 Sep 2018 00:17:07", "url": "https://jasonrbriggs.com/micro/2018/09/07/just-testing.html", "content_text": "Just testing if this post appears in [micro.blog](https://micro.blog)", "content_html": "Just testing if this post appears in micro.blog
", "date_published": "2018-09-07T00:17:07+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/09/07/maybe-micro-blog.html", "title": "Microblog posted at 07 Sep 2018 00:08:58", "url": "https://jasonrbriggs.com/micro/2018/09/07/maybe-micro-blog.html", "content_text": "Maybe [micro.blog](https://micro.blog) is the answer if [mastodon](https://joinmastodon.org/) isn't...", "content_html": "Maybe micro.blog is the answer if mastodon isn't...
", "date_published": "2018-09-07T00:08:58+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/08/21/quick-search.html", "title": "Microblog posted at 21 Aug 2018 18:43:00", "url": "https://jasonrbriggs.com/micro/2018/08/21/quick-search.html", "content_text": "Nothing like a quick search for [#deactiday](https://mstdn.io/tags/deactiday) on twitter...\n\n... (search on the birdsite sucks btw) to re-affirm: wow there's a bunch of idiots there, and it was the right decision to deactivate.", "content_html": "Nothing like a quick search for #deactiday on twitter...
\n... (search on the birdsite sucks btw) to re-affirm: wow there's a bunch of idiots there, and it was the right decision to deactivate.
", "date_published": "2018-08-21T18:43:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/08/17/wilw-followed-thru.html", "title": "Microblog posted at 17 Aug 2018 20:01:00", "url": "https://jasonrbriggs.com/micro/2018/08/17/wilw-followed-thru.html", "content_text": "So [@wilw](https://mastodon.cloud/@wilw) followed through ( [#deactiday](https://mstdn.io/tags/deactiday) ) ...\n\n...boom. Mind blown.", "content_html": "So @wilw followed through ( #deactiday ) ...
\n...boom. Mind blown.
", "date_published": "2018-08-17T20:01:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/08/17/well-i-followed-thru.html", "title": "Microblog posted at 17 Aug 2018 19:52:00", "url": "https://jasonrbriggs.com/micro/2018/08/17/well-i-followed-thru.html", "content_text": "Well I followed thru. :-P [#deactiday](https://mstdn.io/tags/deactiday)", "content_html": "Well I followed thru. :-P #deactiday
", "date_published": "2018-08-17T19:52:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/07/30/regarding-this.html", "title": "Microblog posted at 30 Jul 2018 20:03:00", "url": "https://jasonrbriggs.com/micro/2018/07/30/regarding-this.html", "content_text": "Regarding this... [https://mstdn.io/@jasonrbriggs/100464912999952990](https://mstdn.io/@jasonrbriggs/100464912999952990) ... just saw this article from last year: [https://www.theguardian.com/politics/2017...](https://www.theguardian.com/politics/2017/sep/30/boris-johnson-caught-on-camera-reciting-kipling-in-myanmar-temple). I repeat: idiot of epic proportion.", "content_html": "Regarding this... https://mstdn.io/@jasonrbriggs/100464912999952990 ... just saw this article from last year: https://www.theguardian.com/politics/2017.... I repeat: idiot of epic proportion.
", "date_published": "2018-07-30T20:03:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/07/30/this-is-what-it-looks-like.html", "title": "Microblog posted at 30 Jul 2018 18:48:00", "url": "https://jasonrbriggs.com/micro/2018/07/30/this-is-what-it-looks-like.html", "content_text": "This is what a no-deal Brexit actually looks like: [http://www.politics.co.uk/blogs/2018/07/2...](http://www.politics.co.uk/blogs/2018/07/27/this-is-what-no-deal-brexit-actually-looks-like)\n\n(basically Rees-Mogg, Johnson, and the other hard-liners are idiots of epic proportions)\n", "content_html": "This is what a no-deal Brexit actually looks like: http://www.politics.co.uk/blogs/2018/07/2...
\n(basically Rees-Mogg, Johnson, and the other hard-liners are idiots of epic proportions)
", "date_published": "2018-07-30T18:48:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/07/30/no-deal-brexit.html", "title": "Microblog posted at 30 Jul 2018 18:46:00", "url": "https://jasonrbriggs.com/micro/2018/07/30/no-deal-brexit.html", "content_text": "RT [@ProfBrianCox](https://twitter.com/profbriancox) Simple, clear and to the point. A no deal brexit looks disastrous because it is disastrous. In political slogan terms, no-deal brexit means no-deal brexit. [https://twitter.com/georgeeaton/status...](https://twitter.com/georgeeaton/status/1023887959563620352)", "content_html": "RT @ProfBrianCox Simple, clear and to the point. A no deal brexit looks disastrous because it is disastrous. In political slogan terms, no-deal brexit means no-deal brexit. https://twitter.com/georgeeaton/status...
", "date_published": "2018-07-30T18:46:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/05/19/pygame-or-appdev.html", "title": "Microblog posted at 19 May 2018 11:47:00", "url": "https://jasonrbriggs.com/micro/2018/05/19/pygame-or-appdev.html", "content_text": "Pygame or App Development using Kivy or XCode: [https://jasonrbriggs.com/u/obMdDtN](https://jasonrbriggs.com/u/obMdDtN)", "content_html": "Pygame or App Development using Kivy or XCode: https://jasonrbriggs.com/u/obMdDtN
", "date_published": "2018-05-19T11:47:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/05/10/a-question-about-tkinter.html", "title": "Microblog posted at 10 May 2018 19:30:00", "url": "https://jasonrbriggs.com/micro/2018/05/10/a-question-about-tkinter.html", "content_text": "A question about tkinter update: [https://jasonrbriggs.com/u/obMdB6i](https://jasonrbriggs.com/u/obMdB6i)", "content_html": "A question about tkinter update: https://jasonrbriggs.com/u/obMdB6i
", "date_published": "2018-05-10T19:30:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/04/26/non-apology.html", "title": "Microblog posted at 26 Apr 2018 19:30:00", "url": "https://jasonrbriggs.com/micro/2018/04/26/non-apology.html", "content_text": "[theguardian.com/technology/2018/apr/26/facebook-chiefs...](https://theguardian.com/technology/2018/apr/26/facebook-chiefs-select-committee-session-five-things-we-heard-mike-schroepfer) ...Schroepfer finally apologised: \"I am sorry that journalists feel we are attempting to prevent the truth coming out.\" Erm... isn't that the definition of a non-apology? [https://en.wikipedia.org/wiki/Non-apol...](https://en.wikipedia.org/wiki/Non-apology_apology)", "content_html": "theguardian.com/technology/2018/apr/26/facebook-chiefs... ...Schroepfer finally apologised: \"I am sorry that journalists feel we are attempting to prevent the truth coming out.\" Erm... isn't that the definition of a non-apology? https://en.wikipedia.org/wiki/Non-apol...
", "date_published": "2018-04-26T19:30:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/04/11/taika.html", "title": "Microblog posted at 11 Apr 2018 12:05:00", "url": "https://jasonrbriggs.com/micro/2018/04/11/taika.html", "content_text": "I might have disagreed with [@TaikaWaititi](https://twitter.com/taikawaititi) 20 years ago ([http://www.nzherald.co.nz/entertainment/n...](http://www.nzherald.co.nz/entertainment/news/article.cfm?c_id=1501119&objectid=12028961) ). But then I saw the explicit (and implicit) racism directed at my wife because she looks Chinese (she's not). And I realised as a white male, I'm playing the game in easy mode...\n", "content_html": "I might have disagreed with @TaikaWaititi 20 years ago (http://www.nzherald.co.nz/entertainment/n... ). But then I saw the explicit (and implicit) racism directed at my wife because she looks Chinese (she's not). And I realised as a white male, I'm playing the game in easy mode...
", "date_published": "2018-04-11T12:05:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/04/01/star-wars.html", "title": "Microblog posted at 01 Apr 2018 20:34:00", "url": "https://jasonrbriggs.com/micro/2018/04/01/star-wars.html", "content_text": "So I totally would have watched more than one series of Downton Abbey if I'd realised the Star Wars connection...\n\n![star wars and downton](https://jasonrbriggs.com/micro/2018/04/01/star-wars.png)", "content_html": "So I totally would have watched more than one series of Downton Abbey if I'd realised the Star Wars connection...
\n", "date_published": "2018-04-01T20:34:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2018/04/01/just-in-time.html", "title": "Microblog posted at 01 Apr 2018 19:09:00", "url": "https://jasonrbriggs.com/micro/2018/04/01/just-in-time.html", "content_text": "Just in time? [https://jasonrbriggs.com/u/obMbLq4](https://jasonrbriggs.com/u/obMbLq4)", "content_html": "Just in time? https://jasonrbriggs.com/u/obMbLq4
", "date_published": "2018-04-01T19:09:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2017/05/11/tcl-error.html", "title": "Microblog posted at 11 May 2017 21:30:00", "url": "https://jasonrbriggs.com/micro/2017/05/11/tcl-error.html", "content_text": "Tcl Error: [https://jasonrbriggs.com//u/obLrttP](https://jasonrbriggs.com/u/obLrttP)", "content_html": "Tcl Error: https://jasonrbriggs.com//u/obLrttP
", "date_published": "2017-05-11T21:30:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2017/04/19/russian.html", "title": "Microblog posted at 19 Apr 2017 20:09:00", "url": "https://jasonrbriggs.com/micro/2017/04/19/russian.html", "content_text": "Русский ... Круто! [https://www.mann-ivanov-ferber.ru/books/python-dlya-detej](https://www.mann-ivanov-ferber.ru/books/python-dlya-detej)\n\n![russian-cover](https://jasonrbriggs.com/micro/2017/04/19/russian-cover.png)", "content_html": "Русский ... Круто! https://www.mann-ivanov-ferber.ru/books/python-dlya-detej
\n", "date_published": "2017-04-19T20:09:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2017/04/08/windows-10.html", "title": "Microblog posted at 08 Apr 2017 11:45:00", "url": "https://jasonrbriggs.com/micro/2017/04/08/windows-10.html", "content_text": "[Windows 10](https://jasonrbriggs.com/u/obLrRGk)", "content_html": "", "date_published": "2017-04-08T11:45:00+01:00" }, { "id": "https://jasonrbriggs.com/micro/2017/04/06/thats-pants.html", "title": "Microblog posted at 06 Apr 2017 12:24:00", "url": "https://jasonrbriggs.com/micro/2017/04/06/thats-pants.html", "content_text": "[That's pants!](https://jasonrbriggs.com/u/obLrQSh)\n", "content_html": "", "date_published": "2017-04-06T12:24:00+01:00" }, { "id": "https://jasonrbriggs.com/journal/2023/05/08/activitypub-on-a-static-site.html", "title": "ActivityPub on a (mostly) static site", "url": "https://jasonrbriggs.com/journal/2023/05/08/activitypub-on-a-static-site.html", "content_text": "Following on from [this post](https://jasonrbriggs.com/journal/2023/04/30/mastodon-and-http-sig.html), for anyone who's interested in getting [ActivityPub](https://activitypub.rocks/) integrated on their static site, this is what I've needed to setup/build (some of this may indeed be redundant, but it 'evolved' over time, so easier just to leave alone than fix).\n\nSome not-hugely-relevant background: I have a custom-built site generator, written in Python, pushing files via git to a [Gitea](https://gitea.io/en-us/) instance and pulled via a cronjob to a dir where they're served by Apache2 (with Cloudflare in front). Everything is static, apart from (now) the [inbox](https://www.w3.org/TR/activitypub/#inbox) required for ActivityPub to work.\n\nIn terms of static ActivityPub content, there are a bunch of JSON files required (I'll probably butcher the descriptions of these, but whatever ¯\\\\\\_(ツ)\\_/¯ ):\n\n* [actor](https://jasonrbriggs.com/@me/actor) - effectively your ActivityPub profile information, but importantly this also has your public key.\n* [followers](https://jasonrbriggs.com/@me/followers) - this is an OrderedCollection (an ActivityStreams term) of your followers. For some reason (I forget why now) I'm just pointing this to a separate JSON file: [followers-list](https://jasonrbriggs.com/@me/followers-list) with the actual followers.\n* [outbox](https://jasonrbriggs.com/@me/outbox) - this is the actual content you post in another OrderedCollection.\n\nAlong with these, I've got another JSON \"profile\"...\n\n[jasonrbriggs@jasonrbriggs.com.json](https://jasonrbriggs.com/profile/jasonrbriggs@jasonrbriggs.com.json)\n\n...which is used for [webfinger](https://webfinger.net/) (more on that shortly).\n\nMy rewrite rules for the first set of files look like this:\n\n```\nRewriteRule ^actor$ /@me/actor [R=301,L]\nRewriteRule ^@me$ /@me/actor [R=301,L]\nRewriteRule ^@me/$ /@me/actor [R=301,L]\nRewriteRule ^@jasonrbriggs$ /@me/actor [R=301,L]\nRewriteRule ^@jasonrbriggs/$ /@me/actor [R=301,L]\nRewriteRule ^followers$ /@me/followers\n\n# force content type\nRewriteRule @me/actor - [env=headerjs:1]\nHeader set Content-type application/activity+json env=headerjs\nRewriteRule @me/outbox - [env=headerjs:1]\nHeader set Content-type application/activity+json env=headerjs\n```\n\nFor the aforementioned webfinger, there's one more rewrite rule:\n\n```\nRewriteCond %{QUERY_STRING} (?:^|&)(resource=acct:jasonrbriggs@jasonrbriggs.com$) [NC]\nRewriteRule ^\\.well-known/webfinger /profile/jasonrbriggs@jasonrbriggs.com.json [L]\n```\n\nThat takes care of the discovery aspects of the process (the `self` link in the webfinger profile points to the `actor`).\n\nI do have a couple more rewrite rules for the `@me` directory which redirect browser requests (basically for text/html) to my local archive of \"micro posts\":\n\n```\nRewriteCond %{HTTP:Accept} text/html [NC]\nRewriteRule ^@me$ /micro/ [R=301,L]\nRewriteCond %{HTTP:Accept} text/html [NC]\nRewriteRule ^@me/$ /micro/ [R=301,L]\n```\n\n(Why \"@me\"? Because I was originally planning *@me@jasonrbriggs.com* as my ActivityPub address, before changing my mind and going with *@jasonrbriggs@jasonrbriggs.com*, and I never got around to fixing).\n\nAs mentioned, the only part of my site which is (unfortunately) **not** static is the ActivityPub inbox, because you need to be able to accept POST [follow](https://www.w3.org/TR/activitypub/#follow-activity-outbox) requests and other notification activities from the fediverse. For the inbox, I've built a very simple [Flask](https://palletsprojects.com/p/flask/)/[WSGI](https://wsgi.readthedocs.io/en/latest/) app to do the very minimum (just file-based, no database, hopefully as minimal impact as possible).\n\nI've also built a local (ie. not web-based) command-line Python app which can be used to send an [Accept](https://www.w3.org/TR/activitypub/#accept-activity-inbox) activity to a follow request (it should also add the follower to the follower's list, but I haven't gotten around to that yet); additionally, it retrieves all **new** posted content from the outbox and delivers that content to each follower's inbox. I'm not posting the code to github - at least not yet - because it's a bit of a mess. If anyone's enthusiastic to use unsupported Python code for this, feel free to get in contact.\n\nThe final piece of the puzzle is a separate Mastodon account (I've had one on [mastodon.social](https://mastodon.social) for a while) where you send yourself a follow request, and then accept it - this not only tests that follow/accept works, but then you can see that your posts are correctly appearing at least *somewhere* in the fediverse.\n\nSo the nice part of all this, is that a [micro post](https://jasonrbriggs.com/micro/) on my site is also added to the [outbox](https://jasonrbriggs.com/@me/outbox), and shortly after it now appears on Mastodon (viewable [here](https://mastodon.social/@jasonrbriggs@jasonrbriggs.com) for example).", "content_html": "Following on from this post, for anyone who's interested in getting ActivityPub integrated on their static site, this is what I've needed to setup/build (some of this may indeed be redundant, but it 'evolved' over time, so easier just to leave alone than fix).
\nSome not-hugely-relevant background: I have a custom-built site generator, written in Python, pushing files via git to a Gitea instance and pulled via a cronjob to a dir where they're served by Apache2 (with Cloudflare in front). Everything is static, apart from (now) the inbox required for ActivityPub to work.
\nIn terms of static ActivityPub content, there are a bunch of JSON files required (I'll probably butcher the descriptions of these, but whatever ¯\\_(ツ)_/¯ ):
\nAlong with these, I've got another JSON \"profile\"...
\njasonrbriggs@jasonrbriggs.com.json
\n...which is used for webfinger (more on that shortly).
\nMy rewrite rules for the first set of files look like this:
\nRewriteRule ^actor$ /@me/actor [R=301,L]\nRewriteRule ^@me$ /@me/actor [R=301,L]\nRewriteRule ^@me/$ /@me/actor [R=301,L]\nRewriteRule ^@jasonrbriggs$ /@me/actor [R=301,L]\nRewriteRule ^@jasonrbriggs/$ /@me/actor [R=301,L]\nRewriteRule ^followers$ /@me/followers\n\n# force content type\nRewriteRule @me/actor - [env=headerjs:1]\nHeader set Content-type application/activity+json env=headerjs\nRewriteRule @me/outbox - [env=headerjs:1]\nHeader set Content-type application/activity+json env=headerjs
\nFor the aforementioned webfinger, there's one more rewrite rule:
\nRewriteCond %{QUERY_STRING} (?:^|&)(resource=acct:jasonrbriggs@jasonrbriggs.com$) [NC]\nRewriteRule ^\\.well-known/webfinger /profile/jasonrbriggs@jasonrbriggs.com.json [L]
\nThat takes care of the discovery aspects of the process (the self
link in the webfinger profile points to the actor
).
I do have a couple more rewrite rules for the @me
directory which redirect browser requests (basically for text/html) to my local archive of \"micro posts\":
RewriteCond %{HTTP:Accept} text/html [NC]\nRewriteRule ^@me$ /micro/ [R=301,L]\nRewriteCond %{HTTP:Accept} text/html [NC]\nRewriteRule ^@me/$ /micro/ [R=301,L]
\n(Why \"@me\"? Because I was originally planning @me@jasonrbriggs.com as my ActivityPub address, before changing my mind and going with @jasonrbriggs@jasonrbriggs.com, and I never got around to fixing).
\nAs mentioned, the only part of my site which is (unfortunately) not static is the ActivityPub inbox, because you need to be able to accept POST follow requests and other notification activities from the fediverse. For the inbox, I've built a very simple Flask/WSGI app to do the very minimum (just file-based, no database, hopefully as minimal impact as possible).
\nI've also built a local (ie. not web-based) command-line Python app which can be used to send an Accept activity to a follow request (it should also add the follower to the follower's list, but I haven't gotten around to that yet); additionally, it retrieves all new posted content from the outbox and delivers that content to each follower's inbox. I'm not posting the code to github - at least not yet - because it's a bit of a mess. If anyone's enthusiastic to use unsupported Python code for this, feel free to get in contact.
\nThe final piece of the puzzle is a separate Mastodon account (I've had one on mastodon.social for a while) where you send yourself a follow request, and then accept it - this not only tests that follow/accept works, but then you can see that your posts are correctly appearing at least somewhere in the fediverse.
\nSo the nice part of all this, is that a micro post on my site is also added to the outbox, and shortly after it now appears on Mastodon (viewable here for example).
", "date_published": "2023-05-08T09:44:15+00:00" }, { "id": "https://jasonrbriggs.com/journal/2023/05/03/python-humble-bundle.html", "title": "Python Humble Bundle", "url": "https://jasonrbriggs.com/journal/2023/05/03/python-humble-bundle.html", "content_text": "The second edition of Python for Kids is a part of the [Python Humble Bundle](https://www.humblebundle.com/books/python-no-starch-books) - along with a bunch of other [No Starch](https://nostarch.com) Python books. Pay what you want... but it's for charity (supporting the Python Software Foundation), so why not pay more than you want? ツ\n", "content_html": "The second edition of Python for Kids is a part of the Python Humble Bundle - along with a bunch of other No Starch Python books. Pay what you want... but it's for charity (supporting the Python Software Foundation), so why not pay more than you want? ツ
", "date_published": "2023-05-03T20:17:54+00:00" }, { "id": "https://jasonrbriggs.com/journal/2023/04/30/mastodon-and-http-sig.html", "title": "Mastodon and http sig", "url": "https://jasonrbriggs.com/journal/2023/04/30/mastodon-and-http-sig.html", "content_text": "I've been trying to integrate [ActivityPub](https://www.w3.org/TR/activitypub/) (basically [Mastodon](https://joinmastodon.org/)) into my static site with varying levels of success. The most difficult part is the [inbox](https://www.w3.org/TR/activitypub/#inbox) which is obviously **not** static - there are 3rd party services to help, like [fed.brid.gy](https://fed.brid.gy/), but I had limited success with that unfortuately, so in the end I've rolled my own basic inbox. The next major hurdle was responding to activities (like [follow](https://www.w3.org/TR/activitypub/#follow-activity-outbox) requests for example) -- it is not at all obvious how to sign the request so Mastodon will accept the response. Finally got it working (with the help of a lot of searching and, funnily enough, guidance from ChatGPT - which wasn't perfect, but definitely helped).\n\nThe most important part (and the bit that I really struggled to find examples for) is the signature string, which needs to be formatted like this:\n\n```python\nsignature_string = f'''(request-target): post {url}\nhost: {headers['Host']}\ndate: {now.strftime('%a, %d %b %Y %H:%M:%S GMT')}\ndigest: {headers['Digest']}'''\n```\n\nWhere the digest is the base64-encoded SHA-256 digest of the encoded content:\n\n```python\nhash_algorithm = hashlib.sha256()\nhash_algorithm.update(json_data.encode())\nbody_hash = base64.b64encode(hash_algorithm.digest()).decode()\nheaders['Digest'] = f'SHA-256={body_hash}'\n```\n\nHere's the full example code (note you need a public key on your [actor](https://www.w3.org/TR/activitypub/#actor-objects) profile, with the matching private key pem file stored locally in .ssh/private.pem). The id of the Accept activity response is simply a pre-generated UUID (at some point, I'll put some more effort into storing the stuff locally in a sqlite db, I guess).\n\n```python\nfrom datetime import datetime\nimport time\nimport hashlib\nimport json\nimport base64\nimport sys\n\nimport requests\nfrom Crypto.Signature import pkcs1_15\nfrom Crypto.Hash import SHA256\nfrom Crypto.PublicKey import RSA\n\nnow = datetime.utcnow()\n\nbase_url = 'https://mastodon.social' \nurl = '/users/jasonrbriggs/inbox'\n\ndata = {\n \"@context\": \"https://www.w3.org/ns/activitystreams\",\n \"type\": \"Accept\",\n \"actor\": \"https://jasonrbriggs.com/@me/actor\",\n \"object\": {\n \"type\": \"Follow\",\n \"actor\": \"https://mastodon.social/users/jasonrbriggs\",\n \"object\": \"https://jasonrbriggs.com/@me/actor\"\n },\n \"id\": \"https://jasonrbriggs.com/response/e958f9a9-4330-4df5-8ffa-4a4a1657c0db\",\n \"summary\": \"Accepted follow request\",\n \"published\": \"2023-04-14T22:12:00Z\"\n}\njson_data = json.dumps(data)\n\nkey_id = 'https://jasonrbriggs.com/@me/actor#main-key'\ntimestamp = now.strftime('%Y-%m-%dT%H:%M:%SZ')\n\nheaders = {\n 'Host': 'mastodon.social',\n 'Date': now.strftime('%a, %d %b %Y %H:%M:%S GMT'),\n 'Accept': 'application/json',\n 'Content-Type': 'application/activity+json'\n}\n\nhash_algorithm = hashlib.sha256()\nhash_algorithm.update(json_data.encode())\nbody_hash = base64.b64encode(hash_algorithm.digest()).decode()\nheaders['Digest'] = f'SHA-256={body_hash}'\n\nprivate_key_data = open('.ssh/private.pem', 'rb').read()\nprivate_key = RSA.import_key(private_key_data)\n\nsignature_template = 'keyId=\"{0}\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"{1}\"'\nsignature_headers = 'host date digest'\nsignature_string = f'''(request-target): post {url}\nhost: {headers['Host']}\ndate: {now.strftime('%a, %d %b %Y %H:%M:%S GMT')}\ndigest: {headers['Digest']}'''\n\nsignature = pkcs1_15.new(private_key).sign(SHA256.new(signature_string.encode()))\nsignature_b64 = base64.b64encode(signature).decode()\nhttp_signature = signature_template.format(key_id, signature_b64)\nheaders['Signature'] = http_signature\n\nresponse = requests.post(base_url + url, data=json_data, headers=headers)\nprint(response.status_code, response.content)\n```\n\n(Note: this is an Accept response to a Follow request from my [mastodon.social account](https://mastodon.social/@jasonrbriggs) to my static site - searchable via mastodon.social using [this link](https://mastodon.social/@jasonrbriggs@jasonrbriggs.com)) ", "content_html": "I've been trying to integrate ActivityPub (basically Mastodon) into my static site with varying levels of success. The most difficult part is the inbox which is obviously not static - there are 3rd party services to help, like fed.brid.gy, but I had limited success with that unfortuately, so in the end I've rolled my own basic inbox. The next major hurdle was responding to activities (like follow requests for example) -- it is not at all obvious how to sign the request so Mastodon will accept the response. Finally got it working (with the help of a lot of searching and, funnily enough, guidance from ChatGPT - which wasn't perfect, but definitely helped).
\nThe most important part (and the bit that I really struggled to find examples for) is the signature string, which needs to be formatted like this:
\nsignature_string = f'''(request-target): post {url}\nhost: {headers['Host']}\ndate: {now.strftime('%a, %d %b %Y %H:%M:%S GMT')}\ndigest: {headers['Digest']}'''
\nWhere the digest is the base64-encoded SHA-256 digest of the encoded content:
\nhash_algorithm = hashlib.sha256()\nhash_algorithm.update(json_data.encode())\nbody_hash = base64.b64encode(hash_algorithm.digest()).decode()\nheaders['Digest'] = f'SHA-256={body_hash}'
\nHere's the full example code (note you need a public key on your actor profile, with the matching private key pem file stored locally in .ssh/private.pem). The id of the Accept activity response is simply a pre-generated UUID (at some point, I'll put some more effort into storing the stuff locally in a sqlite db, I guess).
\nfrom datetime import datetime\nimport time\nimport hashlib\nimport json\nimport base64\nimport sys\n\nimport requests\nfrom Crypto.Signature import pkcs1_15\nfrom Crypto.Hash import SHA256\nfrom Crypto.PublicKey import RSA\n\nnow = datetime.utcnow()\n\nbase_url = 'https://mastodon.social' \nurl = '/users/jasonrbriggs/inbox'\n\ndata = {\n \"@context\": \"https://www.w3.org/ns/activitystreams\",\n \"type\": \"Accept\",\n \"actor\": \"https://jasonrbriggs.com/@me/actor\",\n \"object\": {\n \"type\": \"Follow\",\n \"actor\": \"https://mastodon.social/users/jasonrbriggs\",\n \"object\": \"https://jasonrbriggs.com/@me/actor\"\n },\n \"id\": \"https://jasonrbriggs.com/response/e958f9a9-4330-4df5-8ffa-4a4a1657c0db\",\n \"summary\": \"Accepted follow request\",\n \"published\": \"2023-04-14T22:12:00Z\"\n}\njson_data = json.dumps(data)\n\nkey_id = 'https://jasonrbriggs.com/@me/actor#main-key'\ntimestamp = now.strftime('%Y-%m-%dT%H:%M:%SZ')\n\nheaders = {\n 'Host': 'mastodon.social',\n 'Date': now.strftime('%a, %d %b %Y %H:%M:%S GMT'),\n 'Accept': 'application/json',\n 'Content-Type': 'application/activity+json'\n}\n\nhash_algorithm = hashlib.sha256()\nhash_algorithm.update(json_data.encode())\nbody_hash = base64.b64encode(hash_algorithm.digest()).decode()\nheaders['Digest'] = f'SHA-256={body_hash}'\n\nprivate_key_data = open('.ssh/private.pem', 'rb').read()\nprivate_key = RSA.import_key(private_key_data)\n\nsignature_template = 'keyId=\"{0}\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"{1}\"'\nsignature_headers = 'host date digest'\nsignature_string = f'''(request-target): post {url}\nhost: {headers['Host']}\ndate: {now.strftime('%a, %d %b %Y %H:%M:%S GMT')}\ndigest: {headers['Digest']}'''\n\nsignature = pkcs1_15.new(private_key).sign(SHA256.new(signature_string.encode()))\nsignature_b64 = base64.b64encode(signature).decode()\nhttp_signature = signature_template.format(key_id, signature_b64)\nheaders['Signature'] = http_signature\n\nresponse = requests.post(base_url + url, data=json_data, headers=headers)\nprint(response.status_code, response.content)
\n(Note: this is an Accept response to a Follow request from my mastodon.social account to my static site - searchable via mastodon.social using this link)
", "date_published": "2023-04-30T08:14:04+00:00" }, { "id": "https://jasonrbriggs.com/journal/2023/01/21/an-update-on-duckduckgo-search.html", "title": "An update on duckduckgo search", "url": "https://jasonrbriggs.com/journal/2023/01/21/an-update-on-duckduckgo-search.html", "content_text": "After reading the experiences of a number of other folk also having issues with Microsoft Bing (and thereby DuckDuckGo) indexing -- particularly [this comment](https://news.ycombinator.com/item?id=34389645) on Hacker News, I've come to the conclusion it was my fault after all.\n\nAt some point last year, I redirected my older (mostly unused) domain to this site, but using \"cloaking\". Meaning the url in the browser stays the same, and it just serves content from the new domain. Clever enough use of the old site I thought -- however, Bing somehow came to the conclusion that the old domain was the canonical one, so it's indexing pages from that domain instead. Basically I'm proxy mirroring my own site and messing up my indexing as a result.\n\nThe annoying thing in all this -- there's no indication in Bing Webmaster Tools that \"there's an exact duplicate of your content being served from [some other domain]\". Which would've been helpful to figure out where I'd gone wrong... ", "content_html": "After reading the experiences of a number of other folk also having issues with Microsoft Bing (and thereby DuckDuckGo) indexing -- particularly this comment on Hacker News, I've come to the conclusion it was my fault after all.
\nAt some point last year, I redirected my older (mostly unused) domain to this site, but using \"cloaking\". Meaning the url in the browser stays the same, and it just serves content from the new domain. Clever enough use of the old site I thought -- however, Bing somehow came to the conclusion that the old domain was the canonical one, so it's indexing pages from that domain instead. Basically I'm proxy mirroring my own site and messing up my indexing as a result.
\nThe annoying thing in all this -- there's no indication in Bing Webmaster Tools that \"there's an exact duplicate of your content being served from [some other domain]\". Which would've been helpful to figure out where I'd gone wrong...
", "date_published": "2023-01-21T20:10:21+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/12/17/salting-with-spark.html", "title": "Salting with Spark", "url": "https://jasonrbriggs.com/journal/2022/12/17/salting-with-spark.html", "content_text": "Posting this on the off-chance it's useful to someone else...\n\nOn my current project, we have a tonne of [Spark](https://spark.apache.org/) logic which needs to aggregate and (generally) sum data which is grouped by different keys, in order to then apply business rules at the record level (i.e. if the total of amount x, when grouped by a, b and c, is over a threshold then apply one calculation to each record in the group, otherwise apply another - that sort of thing). [Window functions](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.Window.html) are an obvious way to do this. Consider you have employee data and want to get the total salary grouped by employment status and gender, a window example in [PySpark](https://spark.apache.org/docs/latest/api/python/index.html) might look something like this:\n\n```python\nfrom pyspark.sql import functions as f\nfrom pyspark.sql.types import IntegerType\n\nwindow = Window.partitionBy(\"employment_status\", \"gender\")\n\ndf.withColumn(\"total_salary\", f.sum(\"annual_salary\").over(window)) \\\n .select(\"first_name\", \"last_name\", \"gender\", \"employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()\n\n+----------+----------+------+-----------------+-------------+------------+\n|first_name| last_name|gender|employment_status|annual_salary|total_salary|\n+----------+----------+------+-----------------+-------------+------------+\n| | | | | | 3320667.0|\n| Edwin| Abbott| M| | 139549| 8286529.0|\n| Kazuko| Abbott| F| PE| 58642| 2.4893626E7|\n```\n\nWhich works fine, but if you have a huge volume of data (say in the 100's of millions -- obviously we're not likely to be employee data now, but it was easier to find test employee data for these examples :four_leaf_clover:), and you don't have a good distribution of records in each group, then you're likely to hit issues with that skewed data -- where spark is trying to send the data from one group to a particular [executor](https://stackoverflow.com/questions/32621990/what-are-workers-executors-cores-in-spark-standalone-cluster) to accomplish the task and the executor blows as a consequence. Particularly if your data is wide (a large number of columns). \n\nEnter *salting*.\n\nThere are a number of articles on salting (like [this one](https://medium.com/appsflyerengineering/salting-your-spark-to-scale-e6f1c87dd18) on Medium), but the basic principle is to bucket the data in a group using a column with a random number (the salt) -- lets say between 1 and 100 -- so that no single group ends up with too many rows, and then do two passes, aggregation with the salt, and then without. Here's an example of the first pass:\n\n```python\nsalted_window = Window.partitionBy(\"employment_status\", \"gender\", \"salt\") \\\n .orderBy(\"employment_status\", \"gender\", \"salt\")\n\ndf.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .withColumn(\"row_number\", row_number().over(salted_window)) \\\n .withColumn(\"salted_total_salary\", \n f.when(f.col(\"row_number\") == 1,\n sum(f.col(\"annual_salary\")).over(salted_window)).otherwise(lit(0))) \\\n .show()\n```\n\nWe're also using `row_number` in this example, so that only the first record in the group will get the salted total (otherwise we'll get the same number with each record in a group, which causes gross-up problems later). Now we *could* just sum up the salted total salary using the \"unsalted\" window:\n\n```python\nsalted_window = Window.partitionBy(\"employment_status\", \"gender\", \"salt\") \\\n .orderBy(\"employment_status\", \"gender\", \"salt\")\nwindow = Window.partitionBy(\"employment_status\", \"gender\")\n\ndf.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .withColumn(\"row_number\", row_number().over(salted_window)) \\\n .withColumn(\"salted_total_salary\", \n f.when(f.col(\"row_number\") == 1,\n sum(f.col(\"annual_salary\")).over(salted_window))) \\\n .withColumn(\"total_salary\", f.sum(\"salted_total_salary\").over(window)) \\\n .select(\"first_name\", \"last_name\", \"gender\", \"employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()\n```\n\nThe problem with this is that there's no reduction step here (ie. reducing the amount of data spark has to deal with) so immediately unsalting the data simply means all your data (still skewed), plus even more columns (the row number and the salt) is shuffled to an executor. We've not fixed the original problem at all (in fact, made it slightly worse). This should've been obvious looking at that Medium article I linked to above -- each of those examples have a filter to reduce the data volume. We missed that nugget -- but in fact, performing salted, followed by unsalted, window functions did seem to make some difference (at least some of our data sets managed to squeak through) when testing.\n\nSo what's the answer, if you need a total with each of your rows and are hitting problems with skew?\n\nDon't use window functions for these cases. Instead, stick with groupBy and agg, then join back to your original data to use the totals:\n\n```python\nfrom pyspark.sql import functions as f\nfrom pyspark.sql.types import IntegerType\n\nsaltval = f.round(f.rand() * 100)\n\ndf1 = df.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .groupBy(\"employment_status\", \"gender\", \"salt\") \\\n .agg(f.sum(\"annual_salary\").alias(\"salted_total_salary\")) \\\n .groupBy(\"employment_status\", \"gender\") \\\n .agg(f.sum(\"salted_total_salary\").alias(\"total_salary\")) \\\n .orderBy(\"employment_status\", \"gender\") \\\n .alias(\"df1\")\n\ndf.join(df1, (df.employment_status == df1.employment_status) & \n (df.gender == df1.gender), \"leftouter\") \\\n .select(\"first_name\", \"last_name\", \"df1.gender\", \"df1.employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()\n```\n\nNow we are aggregating with the salt and then without - so each step is the data reduction that spark needs to be able to deal with the volume of data in the groups (side note: a broadcast can also be useful in the above).", "content_html": "Posting this on the off-chance it's useful to someone else...
\nOn my current project, we have a tonne of Spark logic which needs to aggregate and (generally) sum data which is grouped by different keys, in order to then apply business rules at the record level (i.e. if the total of amount x, when grouped by a, b and c, is over a threshold then apply one calculation to each record in the group, otherwise apply another - that sort of thing). Window functions are an obvious way to do this. Consider you have employee data and want to get the total salary grouped by employment status and gender, a window example in PySpark might look something like this:
\nfrom pyspark.sql import functions as f\nfrom pyspark.sql.types import IntegerType\n\nwindow = Window.partitionBy(\"employment_status\", \"gender\")\n\ndf.withColumn(\"total_salary\", f.sum(\"annual_salary\").over(window)) \\\n .select(\"first_name\", \"last_name\", \"gender\", \"employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()\n\n+----------+----------+------+-----------------+-------------+------------+\n|first_name| last_name|gender|employment_status|annual_salary|total_salary|\n+----------+----------+------+-----------------+-------------+------------+\n| | | | | | 3320667.0|\n| Edwin| Abbott| M| | 139549| 8286529.0|\n| Kazuko| Abbott| F| PE| 58642| 2.4893626E7|
\nWhich works fine, but if you have a huge volume of data (say in the 100's of millions -- obviously we're not likely to be employee data now, but it was easier to find test employee data for these examples 🍀), and you don't have a good distribution of records in each group, then you're likely to hit issues with that skewed data -- where spark is trying to send the data from one group to a particular executor to accomplish the task and the executor blows as a consequence. Particularly if your data is wide (a large number of columns).
\nEnter salting.
\nThere are a number of articles on salting (like this one on Medium), but the basic principle is to bucket the data in a group using a column with a random number (the salt) -- lets say between 1 and 100 -- so that no single group ends up with too many rows, and then do two passes, aggregation with the salt, and then without. Here's an example of the first pass:
\nsalted_window = Window.partitionBy(\"employment_status\", \"gender\", \"salt\") \\\n .orderBy(\"employment_status\", \"gender\", \"salt\")\n\ndf.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .withColumn(\"row_number\", row_number().over(salted_window)) \\\n .withColumn(\"salted_total_salary\", \n f.when(f.col(\"row_number\") == 1,\n sum(f.col(\"annual_salary\")).over(salted_window)).otherwise(lit(0))) \\\n .show()
\nWe're also using row_number
in this example, so that only the first record in the group will get the salted total (otherwise we'll get the same number with each record in a group, which causes gross-up problems later). Now we could just sum up the salted total salary using the \"unsalted\" window:
salted_window = Window.partitionBy(\"employment_status\", \"gender\", \"salt\") \\\n .orderBy(\"employment_status\", \"gender\", \"salt\")\nwindow = Window.partitionBy(\"employment_status\", \"gender\")\n\ndf.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .withColumn(\"row_number\", row_number().over(salted_window)) \\\n .withColumn(\"salted_total_salary\", \n f.when(f.col(\"row_number\") == 1,\n sum(f.col(\"annual_salary\")).over(salted_window))) \\\n .withColumn(\"total_salary\", f.sum(\"salted_total_salary\").over(window)) \\\n .select(\"first_name\", \"last_name\", \"gender\", \"employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()
\nThe problem with this is that there's no reduction step here (ie. reducing the amount of data spark has to deal with) so immediately unsalting the data simply means all your data (still skewed), plus even more columns (the row number and the salt) is shuffled to an executor. We've not fixed the original problem at all (in fact, made it slightly worse). This should've been obvious looking at that Medium article I linked to above -- each of those examples have a filter to reduce the data volume. We missed that nugget -- but in fact, performing salted, followed by unsalted, window functions did seem to make some difference (at least some of our data sets managed to squeak through) when testing.
\nSo what's the answer, if you need a total with each of your rows and are hitting problems with skew?
\nDon't use window functions for these cases. Instead, stick with groupBy and agg, then join back to your original data to use the totals:
\nfrom pyspark.sql import functions as f\nfrom pyspark.sql.types import IntegerType\n\nsaltval = f.round(f.rand() * 100)\n\ndf1 = df.withColumn(\"salt\", f.lit(saltval).cast(IntegerType())) \\\n .groupBy(\"employment_status\", \"gender\", \"salt\") \\\n .agg(f.sum(\"annual_salary\").alias(\"salted_total_salary\")) \\\n .groupBy(\"employment_status\", \"gender\") \\\n .agg(f.sum(\"salted_total_salary\").alias(\"total_salary\")) \\\n .orderBy(\"employment_status\", \"gender\") \\\n .alias(\"df1\")\n\ndf.join(df1, (df.employment_status == df1.employment_status) & \n (df.gender == df1.gender), \"leftouter\") \\\n .select(\"first_name\", \"last_name\", \"df1.gender\", \"df1.employment_status\", \"annual_salary\", \"total_salary\") \\\n .orderBy(\"last_name\", \"first_name\") \\\n .show()
\nNow we are aggregating with the salt and then without - so each step is the data reduction that spark needs to be able to deal with the volume of data in the groups (side note: a broadcast can also be useful in the above).
", "date_published": "2022-12-17T17:48:27+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/08/06/leaving-duckduckgo-sort-of.html", "title": "Leaving DuckDuckGo... sort of", "url": "https://jasonrbriggs.com/journal/2022/08/06/leaving-duckduckgo-sort-of.html", "content_text": "This is a weird one. [DDG](https://duckduckgo.com) has been my search engine of choice for a number of years, so I also used it as the search engine for this site (since it's [statically generated](https://indieweb.org/static_site)). At some point over the last 3 (I think) months it stopped working - returning no results for any search criteria. Given Bing provides at least some percentage of DDG's content, I went digging in Bing's webmaster tools and found this...\n\n[![bing webmaster tools - screenshot 1](https://jasonrbriggs.com/journal/2022/08/06/bing-1-small.png)](/journal/2022/08/06/bing-1.png)\n\n(*The inspected URL is known to Bing but has some issues which are preventing indexation*)\n\nThere were a few errors reported but nothing that seems like a major issue (missing \"description\" meta, etc), and the indexation issue is even more confounding when you click on the Live Url and see...\n\n[![bing webmaster tools - screenshot 2](https://jasonrbriggs.com/journal/2022/08/06/bing-2-small.png)](/journal/2022/08/06/bing-2.png)\n\n(*URL can be indexed by Bing*)\n\nI fixed some of the most egregious errors, tried getting it to re-index, but regardless, nothing is searchable in DDG...\n\n[https://duckduckgo.com/?q=tkinter+site%3Ajasonrbriggs.com&t=h_&ia=web](https://duckduckgo.com/?q=tkinter+site%3Ajasonrbriggs.com&t=h_&ia=web)\n\nAnd nothing in Bing...\n\n[https://www.bing.com/search?q=tkinter+site%3Ajasonrbriggs.com](https://www.bing.com/search?q=tkinter+site%3Ajasonrbriggs.com)\n\nBut it seems Google has no problem...\n\n[https://www.google.com/search?q=tkinter+site%3Ajasonrbriggs.com](https://www.google.com/search?q=tkinter+site%3Ajasonrbriggs.com)\n\nAs a consequence, I've re-pointed the site search at google search, until I can figure something else out (perhaps [Lunr](https://lunrjs.com/)?), but for the moment it seems like I don't exist in my search engine of choice. Sigh.", "content_html": "This is a weird one. DDG has been my search engine of choice for a number of years, so I also used it as the search engine for this site (since it's statically generated). At some point over the last 3 (I think) months it stopped working - returning no results for any search criteria. Given Bing provides at least some percentage of DDG's content, I went digging in Bing's webmaster tools and found this...
\n\n(The inspected URL is known to Bing but has some issues which are preventing indexation)
\nThere were a few errors reported but nothing that seems like a major issue (missing \"description\" meta, etc), and the indexation issue is even more confounding when you click on the Live Url and see...
\n\n(URL can be indexed by Bing)
\nI fixed some of the most egregious errors, tried getting it to re-index, but regardless, nothing is searchable in DDG...
\nhttps://duckduckgo.com/?q=tkinter+site%3Ajasonrbriggs.com&t=h_&ia=web
\nAnd nothing in Bing...
\nhttps://www.bing.com/search?q=tkinter+site%3Ajasonrbriggs.com
\nBut it seems Google has no problem...
\nhttps://www.google.com/search?q=tkinter+site%3Ajasonrbriggs.com
\nAs a consequence, I've re-pointed the site search at google search, until I can figure something else out (perhaps Lunr?), but for the moment it seems like I don't exist in my search engine of choice. Sigh.
", "date_published": "2022-08-06T08:42:28+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/07/30/python-for-kids-2-and-latex.html", "title": "Python for Kids 2 and LaTeX", "url": "https://jasonrbriggs.com/journal/2022/07/30/python-for-kids-2-and-latex.html", "content_text": "For those who are interested, Python for Kids 2 has been completely rewritten as [LaTeX](https://www.latex-project.org/about/) (using [No Starch](https://nostarch.com)'s style); partially in text files, and partially in [Overleaf](https://overleaf.com):\n\n[![overleaf](https://jasonrbriggs.com/journal/2022/07/30/overleaf-small.png)](/journal/2022/07/30/overleaf.png) \n\nOverleaf was great, particularly for the review process, but I have to say working in LaTeX is an order of magnitude better than using a Word Processor - especially when the files are backed by a git repo (which Overleaf provides) so tracking changes is easy (looking back at the history of changes in a file to see what I changed, is a big win). \n\nCan't comment on how No Starch's editorial staff found working in Overleaf (because we haven't really discussed it), but for me it was all positive...", "content_html": "For those who are interested, Python for Kids 2 has been completely rewritten as LaTeX (using No Starch's style); partially in text files, and partially in Overleaf:
\n\nOverleaf was great, particularly for the review process, but I have to say working in LaTeX is an order of magnitude better than using a Word Processor - especially when the files are backed by a git repo (which Overleaf provides) so tracking changes is easy (looking back at the history of changes in a file to see what I changed, is a big win).
\nCan't comment on how No Starch's editorial staff found working in Overleaf (because we haven't really discussed it), but for me it was all positive...
", "date_published": "2022-07-30T08:34:46+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/07/29/rss-imap.html", "title": "RSS IMAP", "url": "https://jasonrbriggs.com/journal/2022/07/29/rss-imap.html", "content_text": "I've been using [feedly](https://feedly.com) since Google decided [RSS](https://www.lifewire.com/what-is-an-rss-feed-4684568) wasn't a thing any more, and have been pretty happy with it. It wasn't as good as [Google Reader](https://en.wikipedia.org/wiki/Google_Reader), but good enough. The ads are gradually becoming more invasive though, and there's less of the minimalist feel it had when I first started using it, so I've been periodically looking for an alternative.\n\nAfter finding nothing I was particularly enthused by, in the end I've decided on the slightly clunkier (certainly geekier) option: taking Tim Brownawell's Python-based [RSS -> IMAP bridge](https://github.com/tbrownaw/rss-imap), and modifying it to suit my needs.\n\nRSS-IMAP reads feed config entries from an email in an IMAP folder, and then loads the feed items as email messages (if they aren't already present in the feed-specific subfolder) - my version reads config from a yaml file instead, and uses a SQLite database to store an index of feed items that have been loaded. Using the yaml file, because I find it easier to ssh onto my raspberry pi (where this is running) and edit the feed items there; than writing a mail, sending it to myself and then copying into the RSS folder. And using a SQLite DB, because that way I can delete feed emails and they won't be re-loaded automatically. SQLite is ideal for this sort of usage, because there's only a single process writing the data, and the index lookup is fast.\n\nThe main changes can be seen here: \n[https://github.com/jasonrbriggs/rss-imap/compare/master...jasonrbriggs:rss-imap:alt?expand=1](https://github.com/jasonrbriggs/rss-imap/compare/master...jasonrbriggs:rss-imap:alt?expand=1)\n\nOr found in the \"alt\" branch of my fork: \n[https://github.com/jasonrbriggs/rss-imap/tree/alt](https://github.com/jasonrbriggs/rss-imap/tree/alt)\n\nPosting in the unlikely event someone else finds these mods useful...\n\nLong live RSS!!", "content_html": "I've been using feedly since Google decided RSS wasn't a thing any more, and have been pretty happy with it. It wasn't as good as Google Reader, but good enough. The ads are gradually becoming more invasive though, and there's less of the minimalist feel it had when I first started using it, so I've been periodically looking for an alternative.
\nAfter finding nothing I was particularly enthused by, in the end I've decided on the slightly clunkier (certainly geekier) option: taking Tim Brownawell's Python-based RSS -> IMAP bridge, and modifying it to suit my needs.
\nRSS-IMAP reads feed config entries from an email in an IMAP folder, and then loads the feed items as email messages (if they aren't already present in the feed-specific subfolder) - my version reads config from a yaml file instead, and uses a SQLite database to store an index of feed items that have been loaded. Using the yaml file, because I find it easier to ssh onto my raspberry pi (where this is running) and edit the feed items there; than writing a mail, sending it to myself and then copying into the RSS folder. And using a SQLite DB, because that way I can delete feed emails and they won't be re-loaded automatically. SQLite is ideal for this sort of usage, because there's only a single process writing the data, and the index lookup is fast.
\nThe main changes can be seen here:
\nhttps://github.com/jasonrbriggs/rss-imap/compare/master...jasonrbriggs:rss-imap:alt?expand=1
Or found in the \"alt\" branch of my fork:
\nhttps://github.com/jasonrbriggs/rss-imap/tree/alt
Posting in the unlikely event someone else finds these mods useful...
\nLong live RSS!!
", "date_published": "2022-07-29T21:31:22+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/04/29/announcing-python-for-kids-2nd-edition.html", "title": "Announcing: Python for Kids 2nd Edition", "url": "https://jasonrbriggs.com/journal/2022/04/29/announcing-python-for-kids-2nd-edition.html", "content_text": "The 2nd edition of Python for Kids is coming October 2022. What's new? Not an exhaustive list, but it has been completely refreshed for the latest version of Python, as well as being updated for the latest versions of Windows and Ubuntu. New Raspberry Pi instructions are there for those who want to use a Pi to start their coding efforts. There are new programming puzzles, updated examples, and a pretty major tidy up of the text in general. \n\nIt's spring cleaning, refurbishment and good old spit polish in book form!\n\nIf you, or someone you know, are looking to get started with programming, it's currently available from No Starch Press ([https://nostarch.com/python-kids-2nd-edition](https://nostarch.com/python-kids-2nd-edition)) on preorder, for 25% off (make sure you use coupon code PREORDER when checking out).", "content_html": "The 2nd edition of Python for Kids is coming October 2022. What's new? Not an exhaustive list, but it has been completely refreshed for the latest version of Python, as well as being updated for the latest versions of Windows and Ubuntu. New Raspberry Pi instructions are there for those who want to use a Pi to start their coding efforts. There are new programming puzzles, updated examples, and a pretty major tidy up of the text in general.
\nIt's spring cleaning, refurbishment and good old spit polish in book form!
\nIf you, or someone you know, are looking to get started with programming, it's currently available from No Starch Press (https://nostarch.com/python-kids-2nd-edition) on preorder, for 25% off (make sure you use coupon code PREORDER when checking out).
", "date_published": "2022-04-29T19:09:06+00:00" }, { "id": "https://jasonrbriggs.com/journal/2022/04/18/bbc-microbit-with-python-for-kids.html", "title": "BBC micro:bit with Python for Kids", "url": "https://jasonrbriggs.com/journal/2022/04/18/bbc-microbit-with-python-for-kids.html", "content_text": "Janick writes:\n\n> _My son got \"Python for Kids\" (the dutch translation) from Sinterklaas last december (Sinterklaas is the local Santa in Belgium_\n> _and the Netherlands). He really enjoyed it! The weeks following he read and coded almost every day until he finished the book._\n> _Some days after, I mentioned we could investigate if he could use the micro:bit he got the year before to control his games._ \n> _He was really into this idea and we looked for python packages that could make this possible. We didn't find any, and because_ \n> _the bluetooth APIs are a bit difficult to get started with for a kid, I created one myself: [https://github.com/janickr/kaspersmicrobit](https://github.com/janickr/kaspersmicrobit)._\n> _We both find the result really fun and engaging! It makes the games even more impressive and attractive for other kids_ \n> _(like his older sisters). I hope you like it too!_\n\nGlad your son enjoyed the book, and the micro:bit controller looks very cool -- I particularly like the 2-player adaptation of the Bounce game you came up with in the video:\n\n![microbit.gif](https://jasonrbriggs.com/journal/2022/04/18/microbit.gif \"Python for Kids using micro:bit\")", "content_html": "Janick writes:
\n\n\nMy son got \"Python for Kids\" (the dutch translation) from Sinterklaas last december (Sinterklaas is the local Santa in Belgium\nand the Netherlands). He really enjoyed it! The weeks following he read and coded almost every day until he finished the book.\nSome days after, I mentioned we could investigate if he could use the micro:bit he got the year before to control his games. \nHe was really into this idea and we looked for python packages that could make this possible. We didn't find any, and because \nthe bluetooth APIs are a bit difficult to get started with for a kid, I created one myself: https://github.com/janickr/kaspersmicrobit.\nWe both find the result really fun and engaging! It makes the games even more impressive and attractive for other kids \n(like his older sisters). I hope you like it too!
\n
Glad your son enjoyed the book, and the micro:bit controller looks very cool -- I particularly like the 2-player adaptation of the Bounce game you came up with in the video:
\n", "date_published": "2022-04-18T20:28:15+00:00" }, { "id": "https://jasonrbriggs.com/journal/2021/11/16/em-hoc-python.html", "title": "Em Học Python", "url": "https://jasonrbriggs.com/journal/2021/11/16/em-hoc-python.html", "content_text": "[![cover](https://jasonrbriggs.com/journal/2021/11/16/em-hoc-python-cover-small.jpg)](/journal/2021/11/16/em-hoc-python-cover.jpg) The Vietnamese translation of Python for Kids is now available from the publisher [Sputnik Edu](http://shop.sputnikedu.com/?231,em-h%E1%BB%8Dc-python). I think that's something in the region of 12 languages in total now (including English)! 👍", "content_html": "The Vietnamese translation of Python for Kids is now available from the publisher Sputnik Edu. I think that's something in the region of 12 languages in total now (including English)! 👍
", "date_published": "2021-11-16T22:05:18+00:00" }, { "id": "https://jasonrbriggs.com/journal/2021/03/19/spark-on-pi.html", "title": "Spark-on-Pi", "url": "https://jasonrbriggs.com/journal/2021/03/19/spark-on-pi.html", "content_text": "I've built a Docker image for running single-node [Spark](http://spark.apache.org/) and [Hadoop](http://hadoop.apache.org/) (one worker) on a Raspberry Pi, since I couldn't find anything to experiment with. Certainly not suitable for anything other than experimentation, but the image can be found on Docker hub here:\n\n[hub.docker.com/repository/docker/jasonrbriggs/pi-spark](https://hub.docker.com/repository/docker/jasonrbriggs/pi-spark)\n\nThe \"source\", such that it is (dockerfile, etc), can be access from [radicle](https://radicle.xyz/) via this URN:\n\n```\nrad:git:hwd1yreyw4xcjarwtb4yuxtsd5dmip9wx9fr9tomjib1mmtkmojnicnn4bo\n```", "content_html": "I've built a Docker image for running single-node Spark and Hadoop (one worker) on a Raspberry Pi, since I couldn't find anything to experiment with. Certainly not suitable for anything other than experimentation, but the image can be found on Docker hub here:
\nhub.docker.com/repository/docker/jasonrbriggs/pi-spark
\nThe \"source\", such that it is (dockerfile, etc), can be access from radicle via this URN:
\nrad:git:hwd1yreyw4xcjarwtb4yuxtsd5dmip9wx9fr9tomjib1mmtkmojnicnn4bo
",
"date_published": "2021-03-19T22:56:01+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2021/02/05/booting-raspberry-pi-from-external-usb.html",
"title": "Booting Raspberry Pi from External USB",
"url": "https://jasonrbriggs.com/journal/2021/02/05/booting-raspberry-pi-from-external-usb.html",
"content_text": "I wanted to boot my Raspberry Pi 4 from an external SSD connected via a USB-to-SATA cable. According to Jeff Geerling's [video](https://www.youtube.com/watch?v=8tTFgrOCsig), it's pretty straightforward using the latest version of the firmware - but try as I might I couldn't get it to start. Tried re-imaging the SSD; also used the SD card copier, to copy the SD contents across to the SSD; but regardless it didn't seem to detect on boot (it was accessible after starting up using the SD, so I knew it probably wasn't a powering issue).\n\nAfter much muddling around, came across rpi-eeprom-config, and realised that BOOT_ORDER was was set to 0x1 -- according to [this page](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711_bootloader_config.md) that's SD card mode. Also according to that page, the default is supposed to be `0xf41` (try SD, if not found, try USB). Ran `sudo rpi-eeprom-config --edit`, changed the value, saved, rebooted and voila, the SSD was bootable, and has been seemlessly working since then.\n\nI'm sure this info has been posted elsewhere, but given I couldn't find it, posting here in case it's of use to someone else.",
"content_html": "I wanted to boot my Raspberry Pi 4 from an external SSD connected via a USB-to-SATA cable. According to Jeff Geerling's video, it's pretty straightforward using the latest version of the firmware - but try as I might I couldn't get it to start. Tried re-imaging the SSD; also used the SD card copier, to copy the SD contents across to the SSD; but regardless it didn't seem to detect on boot (it was accessible after starting up using the SD, so I knew it probably wasn't a powering issue).
\nAfter much muddling around, came across rpi-eeprom-config, and realised that BOOT_ORDER was was set to 0x1 -- according to this page that's SD card mode. Also according to that page, the default is supposed to be 0xf41
(try SD, if not found, try USB). Ran sudo rpi-eeprom-config --edit
, changed the value, saved, rebooted and voila, the SSD was bootable, and has been seemlessly working since then.
I'm sure this info has been posted elsewhere, but given I couldn't find it, posting here in case it's of use to someone else.
", "date_published": "2021-02-05T22:52:28+00:00" }, { "id": "https://jasonrbriggs.com/journal/2021/01/30/breaking-out-of-loops.html", "title": "Breaking out of loops", "url": "https://jasonrbriggs.com/journal/2021/01/30/breaking-out-of-loops.html", "content_text": "Sherry W writes (excerpted):\n\n> _Excellent book so far for my grandson._\n>\n> _On page 78 should it read?:_\n>\n> _while True:_ \n> _lots of code here_ \n> _lots of code here_ \n> _lots of code here_ \n> _if some value == False_ \n> _break_ \n>\n> _Book is written very well for that age group. It’s great to have a book that is able to explain concepts with simple examples._\n\nThe example on page 78 is not supposed to be executable code (obviously the text \"lots of code here\" repeated 3 times isn't), so it doesn't actually matter if the condition is \"`some_value == False`\" or \"`some_value == True`\". If I was going to write a runnable version of the example, it might look something like this:\n\n```python\nsome_value = True\nwhile True:\n print(\"aaaa\")\n print(\"bbbb\")\n print(\"cccc\")\n if some_value == True:\n break \n```\n\nWhich, if it was run, would print the following just once:\n\n```\naaaa\nbbbb\ncccc\n```\n\nBut you could use True or False in the above example (on the first line and the second-to-last line), and it would work just as well.\n\nHowever a shortcut, not mentioned in the book (because I think simplicity and clarity is better for beginners), is that when you're checking for `True`, you can omit the \"`== True`\" altogether:\n\n```python\nsome_value = True\nwhile True:\n print(\"aaaa\")\n print(\"bbbb\")\n print(\"cccc\")\n if some_value:\n break \n```", "content_html": "Sherry W writes (excerpted):
\n\n\nExcellent book so far for my grandson.
\nOn page 78 should it read?:
\nwhile True:
\n
\n lots of code here
\n lots of code here
\n lots of code here
\n if some value == False
\n breakBook is written very well for that age group. It’s great to have a book that is able to explain concepts with simple examples.
\n
The example on page 78 is not supposed to be executable code (obviously the text \"lots of code here\" repeated 3 times isn't), so it doesn't actually matter if the condition is \"some_value == False
\" or \"some_value == True
\". If I was going to write a runnable version of the example, it might look something like this:
some_value = True\nwhile True:\n print(\"aaaa\")\n print(\"bbbb\")\n print(\"cccc\")\n if some_value == True:\n break
\nWhich, if it was run, would print the following just once:
\naaaa\nbbbb\ncccc
\nBut you could use True or False in the above example (on the first line and the second-to-last line), and it would work just as well.
\nHowever a shortcut, not mentioned in the book (because I think simplicity and clarity is better for beginners), is that when you're checking for True
, you can omit the \"== True
\" altogether:
some_value = True\nwhile True:\n print(\"aaaa\")\n print(\"bbbb\")\n print(\"cccc\")\n if some_value:\n break
",
"date_published": "2021-01-30T11:09:03+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2020/07/23/tkinter-colorchooser-problems-(revisited).html",
"title": "Tkinter colorchooser problems (revisited)",
"url": "https://jasonrbriggs.com/journal/2020/07/23/tkinter-colorchooser-problems-(revisited).html",
"content_text": "Suranga writes:\n\n> _My son and I have been learning Python with your great book. Unfortunately, we hit an issue with Colorchooser -_\n> _the problem appears identical to this one: https://jasonrbriggs.com/journal/2013/05/01/tkinter-colorchooser-problems.html_\n> _In the solution, you suggest we revisit Chapter 1 but can see no mention of a way to ensure IDLE is launched with No Subprocesses._\n> _Have we missed something here? Perhaps there was an earlier version of the book that did not contain this? (ours is the Tenth Printing)._\n> _Thanks for any guidance you can provide!_\n\nNo, you haven't missed anything. In subsequent printings of the book, my advice about using \"No subprocess\" has been removed -- that mode is no longer valid with the versions of Python 3 released since Python for Kids came out in 2012. \n\nInterestingly, despite the fact all the code in the original print was tested by multiple people (including me!), I can't now find a version of python where `from tkinter import *` actually results in `colorchooser.askcolor()` working properly. So in yet later printings (some time after [Jan 2017](https://jasonrbriggs.com/python-for-kids/errata.html#jan-2017)), I changed the instructions to reflect that fact that colorchooser is not imported by default when using `import *`.\n\nThis is now the corrected code:\n\n```python\nfrom tkinter import *\nfrom tkinter import colorchooser\ntk = Tk()\ntk.update()\ncolorchooser.askcolor()\n```\n\n",
"content_html": "Suranga writes:
\n\n\nMy son and I have been learning Python with your great book. Unfortunately, we hit an issue with Colorchooser -\nthe problem appears identical to this one: https://jasonrbriggs.com/journal/2013/05/01/tkinter-colorchooser-problems.html\nIn the solution, you suggest we revisit Chapter 1 but can see no mention of a way to ensure IDLE is launched with No Subprocesses.\nHave we missed something here? Perhaps there was an earlier version of the book that did not contain this? (ours is the Tenth Printing).\nThanks for any guidance you can provide!
\n
No, you haven't missed anything. In subsequent printings of the book, my advice about using \"No subprocess\" has been removed -- that mode is no longer valid with the versions of Python 3 released since Python for Kids came out in 2012.
\nInterestingly, despite the fact all the code in the original print was tested by multiple people (including me!), I can't now find a version of python where from tkinter import *
actually results in colorchooser.askcolor()
working properly. So in yet later printings (some time after Jan 2017), I changed the instructions to reflect that fact that colorchooser is not imported by default when using import *
.
This is now the corrected code:
\nfrom tkinter import *\nfrom tkinter import colorchooser\ntk = Tk()\ntk.update()\ncolorchooser.askcolor()
",
"date_published": "2020-07-23T21:37:32+01:00"
},
{
"id": "https://jasonrbriggs.com/journal/2020/07/05/top-few.html",
"title": "Top Few",
"url": "https://jasonrbriggs.com/journal/2020/07/05/top-few.html",
"content_text": "I was reading [Tim Bray](https://www.tbray.org)'s recent blog posts ([here](https://www.tbray.org/ongoing/When/202x/2020/05/18/TopFew) and [here](https://www.tbray.org/ongoing/When/202x/2020/07/01/More-Topfew-Fun)) about his [Topfew](https://github.com/timbray/topfew) utility with interest, and wondered how my go-to systems programming language ([Nim](https://nim-lang.org)) stacks up compared to [Go](https://golang.org/). I knocked up a quick and dirty implementation and then ran against a 900MB access_log from my own site. A minute or so later I hit CTRL+C, realising my quick and dirty implementation was (a) not quick at all, and (b) perhaps a bit too \"dirty\". ಠ_ಠ\n\nOnce I changed from the naive *read everything into memory* approach, to using Nim's [streams](https://nim-lang.org/docs/streams.html), I ended up with something slightly more acceptable. Caveat: not really optimised (well... apart from compiling with `-d:release --passC:-mcpu=native --boundChecks:off` flags), lazily developed, probably still naive, but at least has border-line acceptable performance ([Github](https://github.com/jasonrbriggs/topfew/)).\n\nResults on my laptop (with an approx 1.5 million line access_log):\n\n| | Elapsed | User | System | vs Go |\n|-------------|--------:|-----:|-------:|------:|\n|Tim's topfew |2.68 |3.86 |0.41 |1.0 |\n|ls/uniq/sort |9.10 |1.76 |0.26 |3.4 |\n|Nim |3.91 |3.65 |0.25 |1.5 |\n\n1.5x isn't brilliant, but it's not bad considering the minimal amount of effort I spent on it. But that led me to wonder, what about Python performance? Another Q&D implementation later (and this time I haven't bothered to dig into the performance at all)...\n\n| | Elapsed | User | System | vs Go |\n|-------------|--------:|-----:|-------:|------:|\n|Tim's topfew |2.68 |3.86 |0.41 |1.0 |\n|ls/uniq/sort |9.10 |1.76 |0.26 |3.4 |\n|Nim |3.91 |3.65 |0.25 |1.5 |\n|Python |8.57 |7.77 |0.79 |3.2 |\n\nNot much better than the uniq/sort version, but the [python version](https://github.com/jasonrbriggs/topfew/blob/master/tf.py) is arguably a little more readable than Nim. One interesting difference between Python and Nim -- the Python version does read the whole file into memory before tokenising...\n\n```python\nwith open(filename) as f:\n for line in f.readlines():\n \t...\n```\n\n...yet the performance was significantly better than my earlier naive Nim implementation which also read the whole file. So it's not just the right tool for the job, but the right technique for the tool.\n\nDo I feel like dusting off the rather rusty [Haskell](https://www.haskell.org/) skills though...?",
"content_html": "I was reading Tim Bray's recent blog posts (here and here) about his Topfew utility with interest, and wondered how my go-to systems programming language (Nim) stacks up compared to Go. I knocked up a quick and dirty implementation and then ran against a 900MB access_log from my own site. A minute or so later I hit CTRL+C, realising my quick and dirty implementation was (a) not quick at all, and (b) perhaps a bit too \"dirty\". ಠ_ಠ
\nOnce I changed from the naive read everything into memory approach, to using Nim's streams, I ended up with something slightly more acceptable. Caveat: not really optimised (well... apart from compiling with -d:release --passC:-mcpu=native --boundChecks:off
flags), lazily developed, probably still naive, but at least has border-line acceptable performance (Github).
Results on my laptop (with an approx 1.5 million line access_log):
\n\n | Elapsed | \nUser | \nSystem | \nvs Go | \n
---|---|---|---|---|
Tim's topfew | \n2.68 | \n3.86 | \n0.41 | \n1.0 | \n
ls/uniq/sort | \n9.10 | \n1.76 | \n0.26 | \n3.4 | \n
Nim | \n3.91 | \n3.65 | \n0.25 | \n1.5 | \n
1.5x isn't brilliant, but it's not bad considering the minimal amount of effort I spent on it. But that led me to wonder, what about Python performance? Another Q&D implementation later (and this time I haven't bothered to dig into the performance at all)...
\n\n | Elapsed | \nUser | \nSystem | \nvs Go | \n
---|---|---|---|---|
Tim's topfew | \n2.68 | \n3.86 | \n0.41 | \n1.0 | \n
ls/uniq/sort | \n9.10 | \n1.76 | \n0.26 | \n3.4 | \n
Nim | \n3.91 | \n3.65 | \n0.25 | \n1.5 | \n
Python | \n8.57 | \n7.77 | \n0.79 | \n3.2 | \n
Not much better than the uniq/sort version, but the python version is arguably a little more readable than Nim. One interesting difference between Python and Nim -- the Python version does read the whole file into memory before tokenising...
\nwith open(filename) as f:\n for line in f.readlines():\n ...
\n...yet the performance was significantly better than my earlier naive Nim implementation which also read the whole file. So it's not just the right tool for the job, but the right technique for the tool.
\nDo I feel like dusting off the rather rusty Haskell skills though...?
", "date_published": "2020-07-05T10:02:33+01:00" }, { "id": "https://jasonrbriggs.com/journal/2020/05/30/problem-with-bouncing-ball.html", "title": "Problem with bouncing ball", "url": "https://jasonrbriggs.com/journal/2020/05/30/problem-with-bouncing-ball.html", "content_text": "Lennier M writes:\n\n> _I am on page 202 of your book, but when I followed your instructions, the ball stopped moving, instead of moving in multiple directions._\n> _Here is my code:_\n>\n> class Ball: \n> def \\_\\_init\\_\\_(self, canvas, color): \n> self.canvas = canvas \n> self.id = canvas.create_oval(10, 10, 25, 25, fill=color) \n> self.canvas.move(self.id, 245, 100) \n> starts = [-3, -2, -1, 1, 2, 3, ] \n> random.shuffle(starts) \n> self.x = starts[0] \n> self.y = -3 \n> self.canvas_width = self.canvas.winfo_width \n> self.canvas_height = self.canvas.winfo_height() \n> def draw(self): \n> self.canvas.move(self.id, self.x, self.y) \n> pos = self.canvas.coords(self.id) \n> if pos[1] <= 0: \n> self.y = 1 \n> if pos[3] >= self.canvas_height: \n> self.y = -1 \n> if pos[0] <= 0: \n> self.x = 3 \n> if pos[2] >= self.canvas_width: \n> self.x = -3 \n> \n> _please help_\n\nIf I run your code I get the following error:\n\n```python\nTraceback (most recent call last):\n File \"test.py\", line 40, inLennier M writes:
\n\n\nI am on page 202 of your book, but when I followed your instructions, the ball stopped moving, instead of moving in multiple directions.\nHere is my code:
\nclass Ball:
\n
\n def __init__(self, canvas, color):
\n self.canvas = canvas
\n self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
\n self.canvas.move(self.id, 245, 100)
\n starts = [-3, -2, -1, 1, 2, 3, ]
\n random.shuffle(starts)
\n self.x = starts[0]
\n self.y = -3
\n self.canvas_width = self.canvas.winfo_width
\n self.canvas_height = self.canvas.winfo_height()
\n def draw(self):
\n self.canvas.move(self.id, self.x, self.y)
\n pos = self.canvas.coords(self.id)
\n if pos[1] <= 0:
\n self.y = 1
\n if pos[3] >= self.canvas_height:
\n self.y = -1
\n if pos[0] <= 0:
\n self.x = 3
\n if pos[2] >= self.canvas_width:
\n self.x = -3please help
\n
If I run your code I get the following error:
\nTraceback (most recent call last):\n File \"test.py\", line 40, in <module>\n ball.draw()\n File \"test.py\", line 26, in draw\n if pos[2] >= self.canvas_width:\nTypeError: '>=' not supported between instances of 'float' and 'method'
\nSo that tells us the line which is failing, but why?
\nIf you look at these two lines, hopefully you'll see the difference (and the reason for your problem):
\n self.canvas_width = self.canvas.winfo_width\n self.canvas_height = self.canvas.winfo_height()
\nThe missing brackets on the first line mean that you haven't actually called the winfo_width
function (or method). So self.canvas_width
isn't a number of pixels - it's actually a reference to the function itself. If we added a print statement at that point in the code it would be even more obvious...
print(self.canvas_width)\n<bound method Misc.winfo_width of <tkinter.Canvas object .!canvas>>\nprint(self.canvas_height)\n400
\nThis is the reason why comparing pos[2]
(which is a number - to be exact it's a floating point number) with self.canvas_width
(which is the reference to a function/method) comes back with the error message: \"'>=' not supported between instances of 'float' and 'method'\".
If you add the missing brackets, you'll hopefully find the ball moves as expected.
", "date_published": "2020-05-30T20:11:32+01:00" }, { "id": "https://jasonrbriggs.com/journal/2020/05/03/online-supermarket-delivery-in-the-uk-needs-to-evolve.html", "title": "Online supermarket delivery in the UK needs to evolve", "url": "https://jasonrbriggs.com/journal/2020/05/03/online-supermarket-delivery-in-the-uk-needs-to-evolve.html", "content_text": "We managed to get a Tesco's delivery last week, which was a challenge - the best we've been do so far is about one delivery every two weeks or so (from different supermarkets). But that basically means sitting online for hours hitting the refresh button to see if a slot becomes available.\n\n_Hunter-gathering in the twenty-first century..._\n\nA couple of hours after our delivery had arrived, I happened to look out the window and see another Tescos delivery being dropped off about two doors down. So not only dumb [UX](https://en.wikipedia.org/wiki/User_experience), but from a logistics perspective, poor design as well.\n\nWhat would make far more sense to me, particularly in this time of lockdown (probably after as well), is you load up your basket with your shopping, then specify half day slots when you'll be at home. i.e. \"here's the 30 things I want, and I can be home for delivery any time Monday to Sunday for the next two weeks\". or \"I can be home for delivery on Friday morning, Saturday morning, and all day Sunday\". Periodically the supermarket runs an algorithm to find the optimal delivery for each order (and obviously you don't get charged if you don't get a delivery) -- perhaps with some prioritisation for those who've been waiting longer for their delivery slot.\n\nThere's nothing massively complicated about this as an algorithm - group addresses in the same street which have an intersecting time period. Then group addresses with close proximity (maybe half a mile or so). Then look for addresses slightly farther apart, but still close enough that delivery can be optimised (half a mile up to a couple of miles) - perhaps some of those can be grouped with one of the first two groups as well. Give each of these delivery groups a certain amount of points. You then rank the deliveries by their points, and by the age of the oldest order in the group -- ungrouped orders would just be ranked by their age -- and send out notifications to the confirmed orders. Discount delivery charges for grouped orders, and if there are any remaining slots available, open them up to adhoc deliveries with a slightly higher charge.\n\nThere's more complexity to take into account, of course - the number of delivery vans versus the number of deliveries per van, distance to the supermarket/depo, etc. But still, the result is likely an improved user experience for everyone, better for the environment and probably more cost effective for the supermarkets.", "content_html": "We managed to get a Tesco's delivery last week, which was a challenge - the best we've been do so far is about one delivery every two weeks or so (from different supermarkets). But that basically means sitting online for hours hitting the refresh button to see if a slot becomes available.
\nHunter-gathering in the twenty-first century...
\nA couple of hours after our delivery had arrived, I happened to look out the window and see another Tescos delivery being dropped off about two doors down. So not only dumb UX, but from a logistics perspective, poor design as well.
\nWhat would make far more sense to me, particularly in this time of lockdown (probably after as well), is you load up your basket with your shopping, then specify half day slots when you'll be at home. i.e. \"here's the 30 things I want, and I can be home for delivery any time Monday to Sunday for the next two weeks\". or \"I can be home for delivery on Friday morning, Saturday morning, and all day Sunday\". Periodically the supermarket runs an algorithm to find the optimal delivery for each order (and obviously you don't get charged if you don't get a delivery) -- perhaps with some prioritisation for those who've been waiting longer for their delivery slot.
\nThere's nothing massively complicated about this as an algorithm - group addresses in the same street which have an intersecting time period. Then group addresses with close proximity (maybe half a mile or so). Then look for addresses slightly farther apart, but still close enough that delivery can be optimised (half a mile up to a couple of miles) - perhaps some of those can be grouped with one of the first two groups as well. Give each of these delivery groups a certain amount of points. You then rank the deliveries by their points, and by the age of the oldest order in the group -- ungrouped orders would just be ranked by their age -- and send out notifications to the confirmed orders. Discount delivery charges for grouped orders, and if there are any remaining slots available, open them up to adhoc deliveries with a slightly higher charge.
\nThere's more complexity to take into account, of course - the number of delivery vans versus the number of deliveries per van, distance to the supermarket/depo, etc. But still, the result is likely an improved user experience for everyone, better for the environment and probably more cost effective for the supermarkets.
", "date_published": "2020-05-03T12:38:42+01:00" }, { "id": "https://jasonrbriggs.com/journal/2020/04/14/long-and-short-dashes.html", "title": "Long and short dashes", "url": "https://jasonrbriggs.com/journal/2020/04/14/long-and-short-dashes.html", "content_text": "Jan vK writes:\n\n> _here's an example from your book that gives an error:_ \n> _count_down_by_twos = list(range(40, 10, −2))_ \n> _SyntaxError: invalid character in identifier_ \n> _please inform me how to solve this problem_\n\nIt looks like you might have copied-and-pasted the code? Perhaps from the digital version of the book? It looks like the -2 in your example is actually a hyphen (i.e. a long dash −) instead of a minus (i.e. a short dash -). So if I try the version of the code you sent, I get the same error:\n\n```python\n>>> count_down_by_twos = list(range(40, 10, −2))\n File \"Jan vK writes:
\n\n\nhere's an example from your book that gives an error:
\n
\ncount_down_by_twos = list(range(40, 10, −2))
\nSyntaxError: invalid character in identifier
\nplease inform me how to solve this problem
It looks like you might have copied-and-pasted the code? Perhaps from the digital version of the book? It looks like the -2 in your example is actually a hyphen (i.e. a long dash −) instead of a minus (i.e. a short dash -). So if I try the version of the code you sent, I get the same error:
\n>>> count_down_by_twos = list(range(40, 10, −2))\n File \"<stdin>\", line 1\n count_down_by_twos = list(range(40, 10, −2))\n ^\nSyntaxError: invalid character in identifier
\nHowever, if I try with the correct character, there's no error:
\n>>> count_down_by_twos = list(range(40, 10, -2))\n>>>
\nThe next question you might ask is what does \"invalid character in identifier\" actually mean? An identifier is the name of something (the name of a keyword, a variable, a function or a class, and so on) -- valid identifiers are a sequence of letters (characters), digits and underscores. In effect you're getting that error message because python doesn't recognise \"−2\" (a long dash followed by 2) as any recognisable keyword, or variable, or anything resembling a valid identifier.
\nHope that helps.
", "date_published": "2020-04-14T20:00:17+01:00" }, { "id": "https://jasonrbriggs.com/journal/2020/01/17/icann-corruption.html", "title": "ICANN corruption", "url": "https://jasonrbriggs.com/journal/2020/01/17/icann-corruption.html", "content_text": "Belatedly... this [article](https://www.theregister.co.uk/2020/01/07/icann_verisign_fees/) about ICANN & dot-com price increases (which does look rather like ICANN corruption, in my opinion), annoyed me more than I can properly express, despite the fact that initially (first few years) the 7% increase will still be less than I'm paying for [dot-nz](https://dnc.org.nz/) domain names. This is pretty obvious profiteering by Verisign, and I worry that this will trickle out from the US to domain names for other countries, inevitably turning the ownership of a domain name from something that's a petty cash expense into a real, and significant, cost. It's particularly concerning if you take into consideration similar news in the [dot-org](https://blog.mozilla.org/blog/2019/12/03/questions-about-org/) [space](https://www.eff.org/press/releases/eff-icann-stop-org-domain-registry-sale-private-equity-firm).\n\nIt irritated enough that I started [looking](https://www.opennic.org/) [at](https://www.namecoin.org/) [alternatives](https://emercoin.com/en/emerdns). However, none of the blockchain domain name options look like a particular economic, straightforward, sure-fire win (paticularly not for a non-technical audience) - even OpenNIC, which is the closest tech to the incumbent, would require jumping through additional hoops because I don't believe my current hosting provider supports DNS alternatives - on their forums, I can't find any mention of OpenNIC apart from a note on a \"Rejected Feature Proposals\" forum, back in 2007, about it being a stale project.\n\nMaybe the global Internet community will eventually route its way around the \"damage\" by selecting a generally acceptable alternative. Or a privacy-focused browser maker like Mozilla will come up with (and promote) a viable domain name system that the other browser makers will have to implement or be left behind.\n\nIn the meantime, perhaps I'll look at redirecting my primary domain elsewhere and route around the problem myself, before the name comes up for renewal in a few years time...", "content_html": "Belatedly... this article about ICANN & dot-com price increases (which does look rather like ICANN corruption, in my opinion), annoyed me more than I can properly express, despite the fact that initially (first few years) the 7% increase will still be less than I'm paying for dot-nz domain names. This is pretty obvious profiteering by Verisign, and I worry that this will trickle out from the US to domain names for other countries, inevitably turning the ownership of a domain name from something that's a petty cash expense into a real, and significant, cost. It's particularly concerning if you take into consideration similar news in the dot-org space.
\nIt irritated enough that I started looking at alternatives. However, none of the blockchain domain name options look like a particular economic, straightforward, sure-fire win (paticularly not for a non-technical audience) - even OpenNIC, which is the closest tech to the incumbent, would require jumping through additional hoops because I don't believe my current hosting provider supports DNS alternatives - on their forums, I can't find any mention of OpenNIC apart from a note on a \"Rejected Feature Proposals\" forum, back in 2007, about it being a stale project.
\nMaybe the global Internet community will eventually route its way around the \"damage\" by selecting a generally acceptable alternative. Or a privacy-focused browser maker like Mozilla will come up with (and promote) a viable domain name system that the other browser makers will have to implement or be left behind.
\nIn the meantime, perhaps I'll look at redirecting my primary domain elsewhere and route around the problem myself, before the name comes up for renewal in a few years time...
", "date_published": "2020-01-18T13:43:59+00:00" }, { "id": "https://jasonrbriggs.com/journal/2019/09/22/problems-with-restarting-the-game.html", "title": "Problems with restarting the game", "url": "https://jasonrbriggs.com/journal/2019/09/22/problems-with-restarting-the-game.html", "content_text": "Serhii writes (excerpted from two emails):\n\n> _I teach programming lessons for the pupils._\n> _We try to do restart button for the \"Bounce\" as it follows:_ \n> _[jasonrbriggs.com/journal/2014/09/03/restarting-the-game.html](https://jasonrbriggs.com/journal/2014/09/03/restarting-the-game.html)_ \n> _...there is a problem in \"command=restart\"._\n\nIf I run your code I get the following error:\n\n```python\nTraceback (most recent call last):\n File \"game1.py\", line 105, inSerhii writes (excerpted from two emails):
\n\n\nI teach programming lessons for the pupils.\nWe try to do restart button for the \"Bounce\" as it follows:
\n
\njasonrbriggs.com/journal/2014/09/03/restarting-the-game.html
\n...there is a problem in \"command=restart\".
If I run your code I get the following error:
\nTraceback (most recent call last):\n File \"game1.py\", line 105, in <module>\n game.add_restart()\n File \"game1.py\", line 86, in add_restart\n self.restart_button = Button(tk, text=\"Click to Restart Game\", command=restart, bg=\"green\")\nNameError: name 'restart' is not defined
\nLooking at your code...
\n def add_restart(self):\n self.restart_button = Button(tk, text=\"Click to Restart Game\", command=restart, bg=\"green\")\n self.restart_button.pack()
\n...the problem is you don't actually have a function called restart
anywhere - which explains the error message \"name 'restart' is not defined\". The easiest way to fix this, is to define that function inside your Game
class, in which case the above function should actually be:
def add_restart(self):\n self.restart_button = Button(tk, text=\"Click to Restart Game\", command=self.restart, bg=\"green\")\n self.restart_button.pack()
\n(note the addition of self
there)\nThe restart function itself should remove the restart button from the screen, move the paddle and ball back to the starting position, and reset the score. I suggest you create a simple function first, just to prove the button works:
\n def restart(self):\n print(\"Restart the game!\")
\nIf you see \"Restart the game!\" printed when clicking the button, you know you're good to start adding the code to do the actual restart (you might also find this post useful: journal/2018/03/04/restarting-the-bounce-game-revisited). The other thing you might want to think about changing, is to only add the restart button if the game is over (so that's a small change to the while
loop at the bottom).
Hope that helps.
", "date_published": "2019-09-22T10:15:27+01:00" }, { "id": "https://jasonrbriggs.com/journal/2019/09/07/idle3-on-ubuntu.html", "title": "IDLE3 on Ubuntu", "url": "https://jasonrbriggs.com/journal/2019/09/07/idle3-on-ubuntu.html", "content_text": "Chris K writes (excerpted):\n\n> _I'm teaching myself and home educating my three young daughters at the same time. Just a little bit every day (excepting Sunday which is entirely reserved_\n> _for pancakes and not inter-computery-things) . Thank you for providing the opportunity for me to introduce the subject of computer programming in a fun way._ \n> _Anyhow, we hit a snag early on that does not seem to get a mention on the publishers site or your blog. When instructed to search for IDLE on the Ubuntu_\n> _software centre nothing of relevance was listed. I had one of the girls do it and she was very disappointed..._ \n> _...I've done some homework and followed [vitux.com/how-to-install-idle-python-ide-on-your-ubuntu](https://vitux.com/how-to-install-idle-python-ide-on-your-ubuntu/) instructions on installing idle3, which worked._\n> _So we are all set to go today._\n> \n> _I don't know how useful this feedback is to you but this is an opportunity to express my appreciation for all your hard work and skill, so I'm taking it._\n\nThe next re-print of Python for Kids will include updated instructions for installing IDLE3 on Ubuntu - which obviously doesn't help anyone reading the current print\nof the book. My steps are pretty similar to the link you've referenced:\n\n![snippet from the book](https://jasonrbriggs.com/journal/2019/09/07/snippet.png) \n\nThanks for the email - it's a good prompting to put something on my site, which others in the same position might come across.\n", "content_html": "Chris K writes (excerpted):
\n\n\nI'm teaching myself and home educating my three young daughters at the same time. Just a little bit every day (excepting Sunday which is entirely reserved\nfor pancakes and not inter-computery-things) . Thank you for providing the opportunity for me to introduce the subject of computer programming in a fun way.
\n
\nAnyhow, we hit a snag early on that does not seem to get a mention on the publishers site or your blog. When instructed to search for IDLE on the Ubuntu\nsoftware centre nothing of relevance was listed. I had one of the girls do it and she was very disappointed...
\n...I've done some homework and followed vitux.com/how-to-install-idle-python-ide-on-your-ubuntu instructions on installing idle3, which worked.\nSo we are all set to go today.I don't know how useful this feedback is to you but this is an opportunity to express my appreciation for all your hard work and skill, so I'm taking it.
\n
The next re-print of Python for Kids will include updated instructions for installing IDLE3 on Ubuntu - which obviously doesn't help anyone reading the current print\nof the book. My steps are pretty similar to the link you've referenced:
\n\n
Thanks for the email - it's a good prompting to put something on my site, which others in the same position might come across.
", "date_published": "2019-09-07T13:50:54+01:00" }, { "id": "https://jasonrbriggs.com/journal/2019/08/02/not-the-normal-knock-off.html", "title": "Not the normal knock-off", "url": "https://jasonrbriggs.com/journal/2019/08/02/not-the-normal-knock-off.html", "content_text": "Usually on Amazon, we see [Python for Kids](https://jasonrbriggs.com/python-for-kids) knock-offs which are an exact copy of the book, with cruddy printing and/or binding. [No Starch](https://nostarch.com/) have a clever binding which allows books to open flat, without falling apart after reading a couple of chapters (clever enough that a few people thought it was actually a failure in the glue) - so these were pretty obviously cheap copies, even without the often misprinted and missing pages.\n\nHowever, an eagle-eyed reader recently notified No Starch of a new type of knock-off -- where they have slightly rewritten the text (I assume just enough to fool a copyright-checking algorithm), and included content from (I think) other sources, to make it even less likely that any automation would flag the book.\n\nFor example, here's an excerpt from Python for Kids...\n\n![pfk excerpt 1](https://jasonrbriggs.com/journal/2019/08/02/pfk-excerpt1.png)\n\nAnd here's the dodgy knock off...\n\n![knockoff excerpt 1](https://jasonrbriggs.com/journal/2019/08/02/knockoff-excerpt1.png)\n\nErm... what the heck is a \"Trump String\"? \n\nHere's another one from PfK:\n\n![pfk excerpt 2](https://jasonrbriggs.com/journal/2019/08/02/pfk-excerpt2.png)\n\nAnd here's the knock off again...\n\n![knockoff excerpt 2](https://jasonrbriggs.com/journal/2019/08/02/knockoff-excerpt2.png)\n\nYeah... way to rewrite it to be more [boooooooring](https://giphy.com/gifs/reaction-uBmiwcS1lGoHGHp0b7/fullscreen), Book Pirates! \n\nThe code examples are pretty much exactly the same in the knock-off (at least the examples I checked) - if badly formatted (including misprinted wingdings characters and other artifacts).\n\nSo, the first part of the book is basically a slightly (and extremely poorly) rewritten knock-off of mine. The second part of the book has things like bubble sort, insertion sort and...\n\n![knockoff pagerank](https://jasonrbriggs.com/journal/2019/08/02/knockoff-pagerank.png)\n\n...because every self-respecting kid needs to how to write a sorting algorithm (by just looking at the code) and how to use numpy and pandas for page-rank???\n\nAnd from there, on to games like Hangman, but written with Python2 and incorrectly formatted as well...\n\n![knockoff hangman](https://jasonrbriggs.com/journal/2019/08/02/knockoff-hangman.png)\n\nA garbage knock-off, and 29 five-star reviews in a couple of weeks, no less (I assume paid for). Interestingly, I clicked through a few of the other reviews by those same reviewers and found more poorly written texts. It's an Amazonian (sic) nest of crappy Python books!\n\nTick tick tick. I wonder how long it'll take Amazon to catch on... \n", "content_html": "Usually on Amazon, we see Python for Kids knock-offs which are an exact copy of the book, with cruddy printing and/or binding. No Starch have a clever binding which allows books to open flat, without falling apart after reading a couple of chapters (clever enough that a few people thought it was actually a failure in the glue) - so these were pretty obviously cheap copies, even without the often misprinted and missing pages.
\nHowever, an eagle-eyed reader recently notified No Starch of a new type of knock-off -- where they have slightly rewritten the text (I assume just enough to fool a copyright-checking algorithm), and included content from (I think) other sources, to make it even less likely that any automation would flag the book.
\nFor example, here's an excerpt from Python for Kids...
\n\nAnd here's the dodgy knock off...
\n\nErm... what the heck is a \"Trump String\"?
\nHere's another one from PfK:
\n\nAnd here's the knock off again...
\n\nYeah... way to rewrite it to be more boooooooring, Book Pirates!
\nThe code examples are pretty much exactly the same in the knock-off (at least the examples I checked) - if badly formatted (including misprinted wingdings characters and other artifacts).
\nSo, the first part of the book is basically a slightly (and extremely poorly) rewritten knock-off of mine. The second part of the book has things like bubble sort, insertion sort and...
\n\n...because every self-respecting kid needs to how to write a sorting algorithm (by just looking at the code) and how to use numpy and pandas for page-rank???
\nAnd from there, on to games like Hangman, but written with Python2 and incorrectly formatted as well...
\n\nA garbage knock-off, and 29 five-star reviews in a couple of weeks, no less (I assume paid for). Interestingly, I clicked through a few of the other reviews by those same reviewers and found more poorly written texts. It's an Amazonian (sic) nest of crappy Python books!
\nTick tick tick. I wonder how long it'll take Amazon to catch on...
", "date_published": "2019-08-02T14:26:36+12:00" }, { "id": "https://jasonrbriggs.com/journal/2019/07/23/string-formatting.html", "title": "String formatting", "url": "https://jasonrbriggs.com/journal/2019/07/23/string-formatting.html", "content_text": "Lou O writes:\n\n> _Hi Jason,_\n> _Read a few good reviews of your book on Amazon._ \n> _One of the reviews pointed out \"The explanation of String formatting needs to be updated. We don't do embedded values using %s anymore._\n> _I recommend skipping the chapters on Turtle Graphics and tkinter._\n> _The introductory chapter on classes and objects is not bad, but the topic is beyond what most kids will need, and they should really focus on imperative / procedural_\n> _programming first using just lists and dictionaries as their basic data structures.\"_ \n> _And I was wondering if those points had been taken into account and updated since then._\n\nIn terms of string formatting, the reviewer is correct but, on the other hand, % formatting hasn't actually been deprecated yet. From the official Python 3 [documentation](https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting):\n\n> The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries\n> correctly). Using the newer formatted string literals, the str.format() interface, or template strings may help avoid these errors. Each of these alternatives\n> provides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility. \n\nI have thought about updating the section on formatting though, just because using `str.format` is the more accepted/modern method -- but this will probably have to wait for a second edition, or perhaps the next major reprint.\n\nIn terms of classes and objects, I don't agree at all. When originally writing the book, I thought rather hard about whether it was worth going into the complexity of that topic and, in the end, came to the conclusion that there is too much in Python which **is** object-oriented, and would be more confusing to explain without at least covering the basics (IMHO).\n\nAnd finally, in regard to the comment about skipping the chapters on turtle and tkinter... sure, if they want a dry book on programming fundamentals, with nothing fun for a kid to experiment with -- one that they will then put down 10 minutes after opening and never return to -- by all means, skip those chapters.\n\nFor everyone else: will your child use the turtle and/or tkinter modules in the future? Probably not. But are they a useful tool to learn how to use those fundamental programming concepts (without needing to install any complicated third party libraries)? Personally, I believe so.", "content_html": "Lou O writes:
\n\n\nHi Jason,\nRead a few good reviews of your book on Amazon.
\n
\nOne of the reviews pointed out \"The explanation of String formatting needs to be updated. We don't do embedded values using %s anymore.\nI recommend skipping the chapters on Turtle Graphics and tkinter.\nThe introductory chapter on classes and objects is not bad, but the topic is beyond what most kids will need, and they should really focus on imperative / procedural\nprogramming first using just lists and dictionaries as their basic data structures.\"
\nAnd I was wondering if those points had been taken into account and updated since then.
In terms of string formatting, the reviewer is correct but, on the other hand, % formatting hasn't actually been deprecated yet. From the official Python 3 documentation:
\n\n\nThe formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries\ncorrectly). Using the newer formatted string literals, the str.format() interface, or template strings may help avoid these errors. Each of these alternatives\nprovides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility.
\n
I have thought about updating the section on formatting though, just because using str.format
is the more accepted/modern method -- but this will probably have to wait for a second edition, or perhaps the next major reprint.
In terms of classes and objects, I don't agree at all. When originally writing the book, I thought rather hard about whether it was worth going into the complexity of that topic and, in the end, came to the conclusion that there is too much in Python which is object-oriented, and would be more confusing to explain without at least covering the basics (IMHO).
\nAnd finally, in regard to the comment about skipping the chapters on turtle and tkinter... sure, if they want a dry book on programming fundamentals, with nothing fun for a kid to experiment with -- one that they will then put down 10 minutes after opening and never return to -- by all means, skip those chapters.
\nFor everyone else: will your child use the turtle and/or tkinter modules in the future? Probably not. But are they a useful tool to learn how to use those fundamental programming concepts (without needing to install any complicated third party libraries)? Personally, I believe so.
", "date_published": "2019-07-23T08:57:31+12:00" }, { "id": "https://jasonrbriggs.com/journal/2019/05/08/bouncing-in-polski.html", "title": "Bouncing in Polski", "url": "https://jasonrbriggs.com/journal/2019/05/08/bouncing-in-polski.html", "content_text": "Marzena writes:\n\n> _I'm writing to you because neither me nor my 11-year old daughter with whom we're learning Python can figure out where the problem is. We get the following error:_ \n> _ ================ RESTART: C:/Users/Enarpol/Desktop/brajan.py ================_ \n> _ Traceback (most recent call last):_ \n> _ File \"C:/Users/Enarpol/Desktop/brajan.py\", line 5, in <module>_ \n> _ class Piłka:_ \n> _ File \"C:/Users/Enarpol/Desktop/brajan.py\", line 20, in Piłka_ \n> _ if pozycja[1] <= 0:_ \n> _ NameError: name 'pozycja' is not defined_ \n> _And the code is exactly like in the book (some words are in Polish, but I assume it's not a problem for you to trace the error despite of it)_\n\nYour problem problem is caused by indentation and the idea of \"scope\" - I guess you're using the Polish language version of the book, so I'm not sure of the correct page number, but in the English language version of the book the section on _Variables and Scope_ (page 84) would be useful to re-read.\n\nIn short, here is the incorrect bit of your code:\n\n```python\n def rysuj(self):\n self.płótno.move(self.id, self.x, self.y)\n pozycja = self.płótno.coords(self.id)\n if pozycja[1] <= 0:\n self.y = 3\n```\n\nIf I re-indent this with visible spaces, to show how it should look, hopefully you can see what you need to fix in the rest of your code:\n\n```python\n def rysuj(self):\n self.płótno.move(self.id, self.x, self.y)\n pozycja = self.płótno.coords(self.id)\n ␣␣␣␣if pozycja[1] <= 0:\n ␣␣␣␣ self.y = 3\n```\n\nWhy does this make a difference? Because in the case of `rysuj` above, the variable `pozycja` is only visible within the function - or to be exact, within the block of code that makes up the function. And how do we create a block of code? Basically through indentation. Your `if` statement was at the same indentation level as `def rysuj(self)`, so it wasn't part of the function and that's why you're getting the error `name 'pozycja' is not defined`.\n\nHope that helps.", "content_html": "Marzena writes:
\n\n\nI'm writing to you because neither me nor my 11-year old daughter with whom we're learning Python can figure out where the problem is. We get the following error:
\n
\n ================ RESTART: C:/Users/Enarpol/Desktop/brajan.py ================
\n Traceback (most recent call last):
\n File \"C:/Users/Enarpol/Desktop/brajan.py\", line 5, in <module>
\n class Piłka:
\n File \"C:/Users/Enarpol/Desktop/brajan.py\", line 20, in Piłka
\n if pozycja[1] <= 0:
\n NameError: name 'pozycja' is not defined
\nAnd the code is exactly like in the book (some words are in Polish, but I assume it's not a problem for you to trace the error despite of it)
Your problem problem is caused by indentation and the idea of \"scope\" - I guess you're using the Polish language version of the book, so I'm not sure of the correct page number, but in the English language version of the book the section on Variables and Scope (page 84) would be useful to re-read.
\nIn short, here is the incorrect bit of your code:
\n def rysuj(self):\n self.płótno.move(self.id, self.x, self.y)\n pozycja = self.płótno.coords(self.id)\n if pozycja[1] <= 0:\n self.y = 3
\nIf I re-indent this with visible spaces, to show how it should look, hopefully you can see what you need to fix in the rest of your code:
\n def rysuj(self):\n self.płótno.move(self.id, self.x, self.y)\n pozycja = self.płótno.coords(self.id)\n ␣␣␣␣if pozycja[1] <= 0:\n ␣␣␣␣ self.y = 3
\nWhy does this make a difference? Because in the case of rysuj
above, the variable pozycja
is only visible within the function - or to be exact, within the block of code that makes up the function. And how do we create a block of code? Basically through indentation. Your if
statement was at the same indentation level as def rysuj(self)
, so it wasn't part of the function and that's why you're getting the error name 'pozycja' is not defined
.
Hope that helps.
", "date_published": "2019-05-08T18:49:57+01:00" }, { "id": "https://jasonrbriggs.com/journal/2019/03/16/traditional-chinese.html", "title": "Traditional Chinese", "url": "https://jasonrbriggs.com/journal/2019/03/16/traditional-chinese.html", "content_text": "你 好!\n\n[![traditional chinese translation cover](https://jasonrbriggs.com/journal/2019/03/16/traditional-chinese-cover-small.jpg)](/journal/2019/03/16/traditional-chinese-cover.jpg)\n\nAvailable from [Wu Nan Books](https://www.wunanbooks.com.tw/product.php?isbn=9789577631688).", "content_html": "你 好!
\n\nAvailable from Wu Nan Books.
", "date_published": "2019-03-16T10:42:51+00:00" }, { "id": "https://jasonrbriggs.com/journal/2019/01/31/stickman-moves.html", "title": "Stickman Moves", "url": "https://jasonrbriggs.com/journal/2019/01/31/stickman-moves.html", "content_text": "Alex Z writes (edited):\n\n> _I'm playing with the last chapter game, cf. the stickmangame7.py file. I'm a little confused about how the key presses are expected_\n> _to cause the character \\[to\\] move._ \n>\n> _If the player hits the right or left key, the character starts moving but keeps moving and doesn't stop unless \\[colliding\\] against a_\n> _wall or a platform. Even jumping on a platform doesn't cause the stick figure to stop. This makes hard to climb to the top parts of the area._\n> _Is it the expected behavior of the game ?_\n>\n> _I am not the first to experience this problem, see the folowing message on stackoverflow:_\n> _[How to move character only when key is pressed down Python](https://stackoverflow.com/questions/45301059/how-to-move-character-only-when-key-is-pressed-down-python)_\n\nYes, that is the expected behaviour of the game. The point is to make it more difficult to reach the top platform, so once the character starts running he doesn't stop, unless he collides with something. However, if you do want to change it so that the character only moves when the key is held down, there's a few fairly minor modifications you can make (which are discussed in that stack overflow article):\n\ni. Add a new function to stop the character moving, by changing the value of the `x` variable to 0. So in the StickFigureSprite sprite class we add this new function:\n```python\nclass StickFigureSprite(Sprite):\n ...\n ...\n ...\n def stop_moving(self, evt):\n self.x = 0\n```\nii. Now we need a way to call the new function. So we add two new key bindings to the `__init__` function of the same class, and set the starting value of the `x` variable to 0 (it's currently set to -2 so that the stick figure starts running as soon as the game starts):\n```python\nclass StickFigureSprite(Sprite):\n def __init__(self, game):\n ...\n ...\n self.x = 0\n ...\n ...\n game.canvas.bind_all('Alex Z writes (edited):
\n\n\nI'm playing with the last chapter game, cf. the stickmangame7.py file. I'm a little confused about how the key presses are expected\nto cause the character [to] move.
\nIf the player hits the right or left key, the character starts moving but keeps moving and doesn't stop unless [colliding] against a\nwall or a platform. Even jumping on a platform doesn't cause the stick figure to stop. This makes hard to climb to the top parts of the area.\nIs it the expected behavior of the game ?
\nI am not the first to experience this problem, see the folowing message on stackoverflow:\nHow to move character only when key is pressed down Python
\n
Yes, that is the expected behaviour of the game. The point is to make it more difficult to reach the top platform, so once the character starts running he doesn't stop, unless he collides with something. However, if you do want to change it so that the character only moves when the key is held down, there's a few fairly minor modifications you can make (which are discussed in that stack overflow article):
\ni. Add a new function to stop the character moving, by changing the value of the x
variable to 0. So in the StickFigureSprite sprite class we add this new function:\n
class StickFigureSprite(Sprite):\n ...\n ...\n ...\n def stop_moving(self, evt):\n self.x = 0
\nii. Now we need a way to call the new function. So we add two new key bindings to the __init__
function of the same class, and set the starting value of the x
variable to 0 (it's currently set to -2 so that the stick figure starts running as soon as the game starts):\nclass StickFigureSprite(Sprite):\n def __init__(self, game):\n ...\n ...\n self.x = 0\n ...\n ...\n game.canvas.bind_all('<KeyRelease-Left>', self.stop_moving)\n game.canvas.bind_all('<KeyRelease-Right>', self.stop_moving)
\nSo with these changes the game starts and the stick man won't move. When you hold the left or right key down, the x
variable is set to -2 or 2 respectively which starts \"him\" moving. When you release the key, it sets the value back to 0, which stops him moving again.
You might notice one slight problem when running the game after this change - the stickman starts quickly and then slows down. This is caused by the keyboard repeating which then impacts the performance of the mainloop
function in the Game class. This is an unfortunate side effect of the way the code for the game is written (the stickman code is not the standard way to handle animation with tkinter -- however it was written this way to hopefully make animation concepts, in programming, slightly easier for a child to understand).
Jobakhan writes (edited):
\n\n\nUsing this code
\n
\nimport sys
\ndef moon_weight():
\n print('Please enter your current Earth weight')
\n weight = float(sys.stdin.readline())
\n print('Please enter the amount your weight might increase each year')
\n increase = float(sys.stdin.readline())
\n print('Please enter the number of years')
\n years = int(sys.stdin.readline())
\n years = years + 1
\n for year in range(1, years):
\n weight = weight + increase
\n moon_weight = weight * 0.165
\n print('Year %s is %s' % (years , moon_weight))then it gives me this:
\n
\n
\nWhy is this happening?
It looks like you're using iPython/Jupyter Notebook to run the examples in the book. Python for Kids wasn't specifically written to work with iPython (nor was the code actually tested with that app), which is why you're having issues. Having said that, I think many of the examples will work, but some, like the code you sent, will need modification.
\nIn the case of the moon_weight
function, it's using sys.stdin.readline()
(that's the sys module, \"standard input\" object, readline function) to read input from the user running the program. There are a couple of ways to read command line input in Python - and in the case of Jupyter it looks like stdin doesn't behave the same way as the Python shell. I found the following in the Jupyter client documentation:
\n\nThis pattern of requesting user input is quite different from how stdin works at a lower level. \nThe Jupyter protocol does not support everything code running in a terminal can do with stdin...
\n
So what's actually happening when you run that code? The function sys.stdin.readline()
returns straight away with an empty string (''
), and Python then throws an error when trying to convert that empty string to a floating point number. If you replace sys.stdin.readline()
in the above code with input()
, the program should then work in jupyter:
weight = float(input())\n...\nincrease = float(input())\n...\nyears = int(input())
",
"date_published": "2019-01-27T10:50:29+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2019/01/26/ipad-pro-and-pythonista.html",
"title": "iPad Pro and Pythonista",
"url": "https://jasonrbriggs.com/journal/2019/01/26/ipad-pro-and-pythonista.html",
"content_text": "Lucia C writes:\n\n> _I am currently reading your book but do not have access to a computer. I do however have my Ipad pro._\n>\n> _There is an app available called Pythonista 3, are you familiar with this app and would you recomend it to follow your book?_\n\nUnfortunately, Pythonista has it's own custom UI library, so I don't believe it supports turtle or tkinter -- the latter chapters of the book rely heavily on tkinter for graphics in the games. Without this you're going to struggle completing all the examples.\n\nIf you only have an iPad, a cheap option might be to purchase a Raspberry Pi (at time of writing a Pi starter kit is [UK£51.99](https://amzn.to/2UivB0e)/[US$79.99](https://amzn.to/2TbQytD)) and use that for your programming activities. While you'll initially need a monitor as well, if you want to stick with the iPad, it looks like it is possible to connect from the iPad to the Pi (so your iPad effectively becomes the monitor) using [VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing) -- more info can be found here in this [instructables article](https://www.instructables.com/id/Use-Your-Tablet-As-Raspberry-Pi-Screen/).\n\nHope that helps.",
"content_html": "Lucia C writes:
\n\n\nI am currently reading your book but do not have access to a computer. I do however have my Ipad pro.
\nThere is an app available called Pythonista 3, are you familiar with this app and would you recomend it to follow your book?
\n
Unfortunately, Pythonista has it's own custom UI library, so I don't believe it supports turtle or tkinter -- the latter chapters of the book rely heavily on tkinter for graphics in the games. Without this you're going to struggle completing all the examples.
\nIf you only have an iPad, a cheap option might be to purchase a Raspberry Pi (at time of writing a Pi starter kit is UK£51.99/US$79.99) and use that for your programming activities. While you'll initially need a monitor as well, if you want to stick with the iPad, it looks like it is possible to connect from the iPad to the Pi (so your iPad effectively becomes the monitor) using VNC -- more info can be found here in this instructables article.
\nHope that helps.
", "date_published": "2019-01-26T10:03:56+00:00" }, { "id": "https://jasonrbriggs.com/journal/2018/09/29/trouble-with-gimp.html", "title": "Trouble with GIMP", "url": "https://jasonrbriggs.com/journal/2018/09/29/trouble-with-gimp.html", "content_text": "Tom writes (excerpted):\n\n> _I'm learning Python from your book and I'm finding it a great resource. However, I'm at the point where I'm creating the StickMan game_\n> _and I'm having issues. I'm using an iMac running MacOS Sierra 10.12.6 The version of GIMP that I downloaded is 2.8.18._\n> _Specifically, I'm at Part III, chapter 15, \"Creating the Game Elements-Preparing a Transparent Image\". Steps 1 through 3 go well,_ \n> _but when I go to \"Select -> All\", there is no \"All\" in the \"Select\" menu. I am also having issues with the paintbrush as a dot._\n> _It shows up as a large square and will blot out most of the 27x30 image that I'm trying to paint. Gimp seems to be prompting me_\n> _to add other layers, but I'm not clear as to how that will affect the image I'm trying to create._\n\nI'm only using a slightly later version of GIMP than you at the moment (2.10), and I don't see any issues - though I'm not running Sierra, I doubt that makes a significant difference. For example, in terms of the Select menu, I can see All at the top:\n\n[![Gimp Select menu](https://jasonrbriggs.com/journal/2018/09/29/select-all-small.png)](/journal/2018/09/29/select-all.png)\n\nIn terms of your problem with the brush, if you look at the brushes palette, the single pixel (1x1 square) is almost at the bottom:\n\n[![Gimp Brushes Palette](https://jasonrbriggs.com/journal/2018/09/29/brush-small.png)](/journal/2018/09/29/brush.png)\n\n(Not entirely sure what you're seeing, but hopefully those screenshots help?)\n\nFinally, regarding layers in Gimp, those aren't necessarily an issue. When you export the image (as a gif or png or anything else) it should collapse the layers into one -- and even if you find them annoying, you can click on the top layer in the layers dialog, select the Layers menu, and then click Merge Down to collapse into the next layer in the list.\n\n\n", "content_html": "Tom writes (excerpted):
\n\n\nI'm learning Python from your book and I'm finding it a great resource. However, I'm at the point where I'm creating the StickMan game\nand I'm having issues. I'm using an iMac running MacOS Sierra 10.12.6 The version of GIMP that I downloaded is 2.8.18.\nSpecifically, I'm at Part III, chapter 15, \"Creating the Game Elements-Preparing a Transparent Image\". Steps 1 through 3 go well, \nbut when I go to \"Select -> All\", there is no \"All\" in the \"Select\" menu. I am also having issues with the paintbrush as a dot.\nIt shows up as a large square and will blot out most of the 27x30 image that I'm trying to paint. Gimp seems to be prompting me\nto add other layers, but I'm not clear as to how that will affect the image I'm trying to create.
\n
I'm only using a slightly later version of GIMP than you at the moment (2.10), and I don't see any issues - though I'm not running Sierra, I doubt that makes a significant difference. For example, in terms of the Select menu, I can see All at the top:
\n\nIn terms of your problem with the brush, if you look at the brushes palette, the single pixel (1x1 square) is almost at the bottom:
\n\n(Not entirely sure what you're seeing, but hopefully those screenshots help?)
\nFinally, regarding layers in Gimp, those aren't necessarily an issue. When you export the image (as a gif or png or anything else) it should collapse the layers into one -- and even if you find them annoying, you can click on the top layer in the layers dialog, select the Layers menu, and then click Merge Down to collapse into the next layer in the list.
", "date_published": "2018-09-29T16:18:29+01:00" }, { "id": "https://jasonrbriggs.com/journal/2018/09/23/modified-idle.html", "title": "Modified IDLE", "url": "https://jasonrbriggs.com/journal/2018/09/23/modified-idle.html", "content_text": "Dean B writes:\n\n> _I'm on page 137 of your book Python For Kids (chapter 10). I noticed a sentence at the top of the page, and have a question on it._\n> _It says \"This won't work if you're using the modified version of IDLE that we set up in Chapter 1.\" I didn't remember seeing anything_\n> _in chapter 1 on a modified version of IDLE. I looked back through chapter 1, but still don't see anything on the matter._\n>\n> _Would you please tell me what page that is on? I'm more curious than anything. I was frustrated with the \"New File\" window so I did_\n> _a search and found IDLEX extensions and installed that. It works quite well for me. I would like to know though how your modified version works._\n>\n> _I'm new to programming and after searching for a good programming language to start with I chose Python, and after looking through_\n> _a lot of books I chose your book \"Python For Kids\". I’m a senior citizen and have found this book to be a great introduction to Python._\n> _Certainly not just for kids as long as the adults are okay with the kid like context. Works for me, and thanks for such a good book._\n\nApologies for the confusion there -- this was a miss when we updated the book for later versions of Python 3. When Python for Kids was released in 2013 (end of 2012), you needed to make a minor modification to the shortcut used for starting up IDLE, to turn off \"subprocess mode\". Without going into too much detail about what that is, effectively if you ran IDLE with subprocess mode on, some of the graphical examples (tkinter, etc) would cause the Shell to hang. This was fixed in a later version of the IDLE runtime, and I removed those instructions from the first chapter on installation -- but completely missed the reference on page 137. Thanks very much for letting me know and I've updated the errata [here](https://jasonrbriggs.com/python-for-kids/errata.html).\n", "content_html": "Dean B writes:
\n\n\nI'm on page 137 of your book Python For Kids (chapter 10). I noticed a sentence at the top of the page, and have a question on it.\nIt says \"This won't work if you're using the modified version of IDLE that we set up in Chapter 1.\" I didn't remember seeing anything\nin chapter 1 on a modified version of IDLE. I looked back through chapter 1, but still don't see anything on the matter.
\nWould you please tell me what page that is on? I'm more curious than anything. I was frustrated with the \"New File\" window so I did\na search and found IDLEX extensions and installed that. It works quite well for me. I would like to know though how your modified version works.
\nI'm new to programming and after searching for a good programming language to start with I chose Python, and after looking through\na lot of books I chose your book \"Python For Kids\". I’m a senior citizen and have found this book to be a great introduction to Python.\nCertainly not just for kids as long as the adults are okay with the kid like context. Works for me, and thanks for such a good book.
\n
Apologies for the confusion there -- this was a miss when we updated the book for later versions of Python 3. When Python for Kids was released in 2013 (end of 2012), you needed to make a minor modification to the shortcut used for starting up IDLE, to turn off \"subprocess mode\". Without going into too much detail about what that is, effectively if you ran IDLE with subprocess mode on, some of the graphical examples (tkinter, etc) would cause the Shell to hang. This was fixed in a later version of the IDLE runtime, and I removed those instructions from the first chapter on installation -- but completely missed the reference on page 137. Thanks very much for letting me know and I've updated the errata here.
", "date_published": "2018-09-23T11:16:24+01:00" }, { "id": "https://jasonrbriggs.com/journal/2018/05/19/pygame-or-app-development-using-kivy-or-xcode.html", "title": "Pygame or App Development using Kivy or XCode?", "url": "https://jasonrbriggs.com/journal/2018/05/19/pygame-or-app-development-using-kivy-or-xcode.html", "content_text": "Sunil writes:\n\n> _I would, first of all, like to thank you for the amazing book you have written \"Python for Kids\"_ \n> _It's really helped my nephew learn Coding in a very exciting and fun way._ \n> _He is now very keen on continuing with Python. He is 8._ \n> _But at this point, I do not know what would be the next set of things to teach him._\n> _Should we proceed with learning Pygame or App Development using Kivy or XCode. I am a little confused on this matter._ \n> _I tried a bit of reading online, but it did not help my decision making._\n>\n> _What would you suggest is the best Python learning path for an 8-year-old after having followed your book._\n\nI'm quite partial to the idea of Pygame as a natural progression from the games in the book. Adapting the Bounce or Stickman game to use Pygame, instead of tkinter, seems like a good way to get started, and then Pygame has support for audio ([mixer](https://www.pygame.org/docs/ref/mixer.html)) and [joystick](https://www.pygame.org/docs/ref/joystick.html) modules, so there's opportunities to enhance and extend the games to add new features. This would be building on learning from the book, which I think is a nice way to move forward. It's certainly going to be the easiest way to get some instant feedback as well (since it's not hard to get up-and-running), so ![thumb's up](https://jasonrbriggs.com/img/thumbs-up-2x.png) from that perspective.\n\nI don't know a lot about Kivy - so I can't really comment on how suitable it would be for an 8 year old -- but even if it proved too difficult, if he's interested in mobile apps, then I don't think that time would be [wasted](https://www.edutopia.org/blog/failure-essential-learning-bob-lenz).\n\nXCode will probably mean learning a new language (depending on what your nephew wants to do with it). If iOS apps, then the options are [Objective-C](https://en.wikipedia.org/wiki/Objective-C) or [Swift](https://en.wikipedia.org/wiki/Swift_(programming_language)) -- which is not to say you're entirely limited to those languages, but you're going to find the most community support with one of the primary languages. Of the two, Swift is the most approachable (IMO), but I still wouldn't call that easy going for a child to pick up.\n\nSo with very limited experience in the other two options, I guess my personal preference would be Pygame, then Kivy, finally XCode. Do let me know how you get on...\n\nReference links for other readers:\n\n* Pygame: [pygame.org](https://www.pygame.org/), [Getting started documentation](https://www.pygame.org/wiki/GettingStarted)\n* Kivy: [kivy.org](https://kivy.org/), [Getting started documentation](https://kivy.org/docs/gettingstarted/intro.html)\n* XCode: [developer.apple.com/xcode](https://developer.apple.com/xcode/), [Getting started documentation (iOS)](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/) ", "content_html": "Sunil writes:
\n\n\nI would, first of all, like to thank you for the amazing book you have written \"Python for Kids\"
\n
\nIt's really helped my nephew learn Coding in a very exciting and fun way.
\nHe is now very keen on continuing with Python. He is 8.
\nBut at this point, I do not know what would be the next set of things to teach him.\nShould we proceed with learning Pygame or App Development using Kivy or XCode. I am a little confused on this matter.
\nI tried a bit of reading online, but it did not help my decision making.What would you suggest is the best Python learning path for an 8-year-old after having followed your book.
\n
I'm quite partial to the idea of Pygame as a natural progression from the games in the book. Adapting the Bounce or Stickman game to use Pygame, instead of tkinter, seems like a good way to get started, and then Pygame has support for audio (mixer) and joystick modules, so there's opportunities to enhance and extend the games to add new features. This would be building on learning from the book, which I think is a nice way to move forward. It's certainly going to be the easiest way to get some instant feedback as well (since it's not hard to get up-and-running), so from that perspective.
\nI don't know a lot about Kivy - so I can't really comment on how suitable it would be for an 8 year old -- but even if it proved too difficult, if he's interested in mobile apps, then I don't think that time would be wasted.
\nXCode will probably mean learning a new language (depending on what your nephew wants to do with it). If iOS apps, then the options are Objective-C or Swift -- which is not to say you're entirely limited to those languages, but you're going to find the most community support with one of the primary languages. Of the two, Swift is the most approachable (IMO), but I still wouldn't call that easy going for a child to pick up.
\nSo with very limited experience in the other two options, I guess my personal preference would be Pygame, then Kivy, finally XCode. Do let me know how you get on...
\nReference links for other readers:
\nFeng writes:
\n\n\nI bought a chinese version of your book.\nwhen i tried the paddle ball at this step: 'Bounce (example 4) - ball moving up and down'\nat the first part of the code, you add a line tk.update(). I cannot see why this is\nnecessary, since there are no balls moving at all. Then, i comment it with a '#'.
\nNow, it comes with a problem, i failed to see the ball move down, it seems stuck at the\ntop line of the canvas. I tried to print the variable 'pos', and it shows as follows:
\n
\n------------------(some part of the outcome)
\n[255.0, 1.0, 270.0, 16.0]
\n[255.0, 0.0, 270.0, 15.0]
\n[255.0, -1.0, 270.0, 14.0]
\nhow did this happen, why the first 'tk.update()' cannot be omitted?
The first call to tk.update()
isn't strictly necessary - but what it does do is to force a \"wait\" until all the Tk user interface events have been processed.
When you call pack
to tell your Tk components to resize and display themselves in the right place, you're actually sending a message to a whole separate process (this is the Tk event loop). Let's imagine it took 1 minute for each component to set itself up, and you had 10 components in the window. If you called pack
it wouldn't take 10 minutes to complete that function call -- it would actually complete almost instantly. Behind the scenes however, the components are busy re-arranging themselves to fit in the window (and in this imaginary scenario, that process would then take 10 minutes to complete).
Try running this code (create a file and run it in IDLE):
\nfrom tkinter import *\ntk = Tk()\ncanvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)\ncanvas.pack()\nprint(canvas.winfo_height())
\nYou'll get 1. That's because the canvas hasn't finished rearranging itself by the time you call winfo_height
. Now try typing the first 4 lines of the code into the IDLE shell -- wait a few seconds then enter the last line:
print(canvas.winfo_height())
\nNow you'll get 400 (i.e. 400 pixels high). Because you've given the canvas time to complete.
\nIn summary, pack
is saying \"ok Tk components, re-arrange yourselves on the screen\" and update
is saying: \"ok Tk, I want to wait for that to complete\". Which is why, if you remove the update
call, inside the __init__
function of the Ball class, it calculates a height of 1, and the code no longer works correctly.
Perhaps just in time for Google shutting down its goo.gl url shortener, here's a potential alternative: nimwhistle, an algorithmic URL shortener loosely based on the ideas in Whistle, but with a few minor modifications (URL patterns in the form of dir/YYYY/mm/dd/filename; 'favourite', fixed or non-standard URLs stored in a fixed-line-length file), and a CGI-based redirection service. 462KB compiled, Apache2 licensed. Not guaranteed for any purpose, because it was a hack-job/experiment, put together in a few hours.
\nUpdate: somewhat stupidly, forgot to mention, nimwhistle is already in use here (for example, https://jasonrbriggs.com/u/f1 redirects to Python for Kids)
", "date_published": "2018-04-01T18:45:00+00:00" }, { "id": "https://jasonrbriggs.com/journal/2018/03/04/restarting-the-bounce-game-revisited.html", "title": "Restarting the Bounce game (revisited)", "url": "https://jasonrbriggs.com/journal/2018/03/04/restarting-the-bounce-game-revisited.html", "content_text": "Robin T writes (excerpted):\n\n> _I am currently at chapter 14, i already made my first game called \"Bounce\"._\n> _When the game is over, i want the user to push a button or a mouse click to restart the game._\n> _But i don't know how to do this._\n\nSomeone else asked a similar question a few years ago, so here's my post from back then, with some ideas about adding a restart button: [\"Restarting the game\"](https://jasonrbriggs.com/journal/2014/09/03/restarting-the-game.html). In terms of creating a function to restart the game, you might want to use the canvas `coords` function to move the ball and paddle back to their starting position, and then set the values of all the other variables to the same as they started as well (for example, setting the `hit_bottom` variable to `False`; if you've added a score, setting the score back to zero; and so on). `coords` takes 5 parameters: the id of the object to move, the x and y position and the width and height of the object. So moving both objects back to their starting position might look something like this:\n\n```python\nself.canvas.coords(self.paddle.id, 200, 300, 300, 310)\nself.canvas.coords(self.ball.id, 245, 100, 260, 115)\n```\n\nHopefully that helps.", "content_html": "Robin T writes (excerpted):
\n\n\nI am currently at chapter 14, i already made my first game called \"Bounce\".\nWhen the game is over, i want the user to push a button or a mouse click to restart the game.\nBut i don't know how to do this.
\n
Someone else asked a similar question a few years ago, so here's my post from back then, with some ideas about adding a restart button: \"Restarting the game\". In terms of creating a function to restart the game, you might want to use the canvas coords
function to move the ball and paddle back to their starting position, and then set the values of all the other variables to the same as they started as well (for example, setting the hit_bottom
variable to False
; if you've added a score, setting the score back to zero; and so on). coords
takes 5 parameters: the id of the object to move, the x and y position and the width and height of the object. So moving both objects back to their starting position might look something like this:
self.canvas.coords(self.paddle.id, 200, 300, 300, 310)\nself.canvas.coords(self.ball.id, 245, 100, 260, 115)
\nHopefully that helps.
", "date_published": "2018-03-04T15:25:00+00:00" }, { "id": "https://jasonrbriggs.com/journal/2018/02/19/problem-with-paddle-ball-animation.html", "title": "Problem with paddle-ball animation", "url": "https://jasonrbriggs.com/journal/2018/02/19/problem-with-paddle-ball-animation.html", "content_text": "Hayden B writes:\n\n> _I am trying to code the bouncing red ball in Chapter 13 but the animation is not working._\n> _I have checked the code, and it makes sense, but I am getting these errors when I run:_\n>\n> _RESTART: C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py_\n> _Traceback (most recent call last):_\n> _ File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py\", line 33, in <module>_\n> _ ball.draw()_\n> _ File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py\", line 15, in draw_\n> _ self.canvas.move(self.id, self.x, self.y)_\n> _ File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\tkinter\\__init__.py\", line 2585, in move_\n> _ self.tk.call((self._w, 'move') + args)_\n> _\\_tkinter.TclError: invalid command name \".!canvas\"_\n>\n> _...and the red ball gets \"stuck\" at the top \"jiggling\" but not bouncing or returning down as it is supposed to._\n> _I cannot figure out what the problem is. Can you help?_\n\nYour code is almost right, there's just one thing you've mistyped. Here's a snippet from my [code](https://jasonrbriggs.com/python-for-kids/chapter13/bounce4.py.txt):\n\n```python\ncanvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)\ncanvas.pack()\ntk.update()\n```\n\nAnd here's your code:\n\n```python\ncanvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)\ncanvas.pack()\ntk.update\n```\n\nCheck the difference in the last line. Why do the missing brackets cause such a problem? The reason is that Python can't calculate the height of the canvas (400 pixels) until you call `pack()` and then `update()`. You are calling `tk.update` which is effectively just dumping information about the function, rather than calling the function itself. Here's what happens if I try that code:\n\n```python\n>>> tk.update\nHayden B writes:
\n\n\nI am trying to code the bouncing red ball in Chapter 13 but the animation is not working.\nI have checked the code, and it makes sense, but I am getting these errors when I run:
\nRESTART: C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py\nTraceback (most recent call last):\n File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py\", line 33, in <module>\n ball.draw()\n File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\Files .py\\paddleball.py\", line 15, in draw\n self.canvas.move(self.id, self.x, self.y)\n File \"C:\\Users\\rf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\tkinter__init__.py\", line 2585, in move\n self.tk.call((self._w, 'move') + args)\n_tkinter.TclError: invalid command name \".!canvas\"
\n...and the red ball gets \"stuck\" at the top \"jiggling\" but not bouncing or returning down as it is supposed to.\nI cannot figure out what the problem is. Can you help?
\n
Your code is almost right, there's just one thing you've mistyped. Here's a snippet from my code:
\ncanvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)\ncanvas.pack()\ntk.update()
\nAnd here's your code:
\ncanvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)\ncanvas.pack()\ntk.update
\nCheck the difference in the last line. Why do the missing brackets cause such a problem? The reason is that Python can't calculate the height of the canvas (400 pixels) until you call pack()
and then update()
. You are calling tk.update
which is effectively just dumping information about the function, rather than calling the function itself. Here's what happens if I try that code:
>>> tk.update\n<bound method Misc.update of <tkinter.Tk object .>>
\nAnd, because you aren't actually calling the update
function, this line...
self.canvas_height = self.canvas.winfo_height()
\n...actually results in canvas_height
being 1 pixel, rather than 400. As a consequence, your ball then gets stuck jiggling at the top of the screen because both these if-statements end up being true:
if pos[1] <= 0:\n self.y = 1\n if pos[3] >= self.canvas_height:\n self.y = -1
\n(so pos[1] ends up being less than or equal to 0, and pos[3] ends up being >= to the canvas_height)
\nBy the way, you can ignore the error message -- that has nothing to do with your code. When you close the game window, your program is still trying to call the move
function and so you get an error message because the canvas no longer exists (effectively).
Hope that helps.
", "date_published": "2018-02-19T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2018/02/11/trouble-with-turtles.html", "title": "Trouble with turtles", "url": "https://jasonrbriggs.com/journal/2018/02/11/trouble-with-turtles.html", "content_text": "Theodore M writes:\n\n> _Hello. Working in python with my daughter, but stuck on this error:_\n>\n> _Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)_\n> _[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin_\n> _Type \"copyright\", \"credits\" or \"license()\" for more information._\n> _>>> import turtle_\n> _Traceback (most recent call last):_\n> _File \"\\Theodore M writes:
\n\n\nHello. Working in python with my daughter, but stuck on this error:
\nPython 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)\n[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin\nType \"copyright\", \"credits\" or \"license()\" for more information.\n>>> import turtle\nTraceback (most recent call last):\n File \"\\<pyshell#0>\", line 1, in
\n\n import turtle\n File \"/Users/mac/Documents/turtle.py\", line 2, in \n t=turtle.Pen()\nAttributeError: module 'turtle' has no attribute 'Pen'
It looks as if you might have created a file called turtle.py
in your Documents directory (/Users/mac/Documents
), and because you're running IDLE from the same directory (I assume), that file is being loaded before the actual turtle module. If you delete this file and try again, hopefully you'll have more success.
Update: for people having a similar problem on Windows (or really any Operating System), who can't find the file to delete, one option is to enter this into the shell:
\nimport turtle\nprint(turtle.__file__)
\nThat will give you the full path. For example:
\n>>> print(turtle.__file__)\nC:\\Users\\jason\\AppData\\Local\\Programs\\Python\\Python37-32\\turtle.py
",
"date_published": "2018-02-11T23:52:53+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2018/01/12/becoming-an-expert.html",
"title": "Becoming an expert?",
"url": "https://jasonrbriggs.com/journal/2018/01/12/becoming-an-expert.html",
"content_text": "Femi A writes:\n\n> _I just got your book: Python for kids and I’m excited to start reading it. I am 36 years old and I would like to learn_\n> _computer programming. I figure python would be a good place to start. Is it possible to become an expert at python in_\n> _6 months with intensive efforts? And if it is can you please let me know how to go about that, the steps to take etc..._\n\nI would say this isn't necessarily a Python, nor even a general computer programming question. It's more a question about how you define expertise, what that means from a learning perspective, and what your goals really are. If you define expertise in terms of [Malcolm Gladwell's 10,000 hour rule](https://en.wikipedia.org/wiki/Outliers_(book)) and spend 4-5 hours a day at it, you'll be an \"expert\" in 6 years or so [1]. So if your goal is to call yourself an \"expert\", then that's probably your timeline.\n\nIf your goal is to develop some software, make a meaningful contribution to an open source project, or something along those lines, and are well motivated, it's certainly possible to do that, and more, with 6 months of dedicated effort. So, how to get to the point where you're at least confident in your coding? Start with a beginners book, funnel that knowledge in developing a few simple projects to build your experience; then perhaps look for a more advanced Python book (O'Reilly's Python Cookbook might be a good option), followed by some more advanced projects, again for the experience. Just remember, it's more important to be coding than reading about it.\n\nHope that helps.\n\n\\[1\\]: Also see this Business Insider [article](https://www.businessinsider.com/new-study-destroys-malcolm-gladwells-10000-rule-2014-7) for a counterpoint to the 10K hour principle.",
"content_html": "Femi A writes:
\n\n\nI just got your book: Python for kids and I’m excited to start reading it. I am 36 years old and I would like to learn\ncomputer programming. I figure python would be a good place to start. Is it possible to become an expert at python in\n6 months with intensive efforts? And if it is can you please let me know how to go about that, the steps to take etc...
\n
I would say this isn't necessarily a Python, nor even a general computer programming question. It's more a question about how you define expertise, what that means from a learning perspective, and what your goals really are. If you define expertise in terms of Malcolm Gladwell's 10,000 hour rule and spend 4-5 hours a day at it, you'll be an \"expert\" in 6 years or so [1]. So if your goal is to call yourself an \"expert\", then that's probably your timeline.
\nIf your goal is to develop some software, make a meaningful contribution to an open source project, or something along those lines, and are well motivated, it's certainly possible to do that, and more, with 6 months of dedicated effort. So, how to get to the point where you're at least confident in your coding? Start with a beginners book, funnel that knowledge in developing a few simple projects to build your experience; then perhaps look for a more advanced Python book (O'Reilly's Python Cookbook might be a good option), followed by some more advanced projects, again for the experience. Just remember, it's more important to be coding than reading about it.
\nHope that helps.
\n[1]: Also see this Business Insider article for a counterpoint to the 10K hour principle.
", "date_published": "2018-01-12T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/11/12/broken-parental-controls.html", "title": "Apple's Broken Parental Controls", "url": "https://jasonrbriggs.com/journal/2017/11/12/broken-parental-controls.html", "content_text": "What's a nice way to give a kid a limited amount of spending freedom, and letting them buy some things without being able to decimate your credit card? iTunes Voucher -- seems reasonable right?\n\nSo... redeeming voucher... _Enter Apple ID password_. Okay. _Use camera to enter code_. That's helpful. _Please enter your credit card security code_. Wait, what? Sigh. Fine.\n\nHand iPad back to kid. \"Right, you can buy something now.\"\n\n\"How about this one?\"\n\n\"Nooo that's too expensive. Find another one.\"\n\n\"What about this?\"\n\n\"Yes okay, that works. You can click this Buy button here.\"\n\n\"Pa??\" iPad thrust back into your hands.\n\n_Enter Apple ID password_\n\nSigh. Okay. Why the heck did I bother to add a nice long, secure password for his account?\n\n_Ask for your parent's approval_. Click Ask... time passes... Nothing happened. Huh? Click Buy again.\n\n_Enter Apple ID password_.\n\nWTH? Just did that! For. The. Same. Game.\n\n_Ask for your parent's approval (they can also authorise on this device)._ Yes, but that defeats the purpose. The whole point was to let the kid buy a few things himself. Click Ask.\n\nA message arrives on my phone: _Your iDevice-obsessed post-toddler wants to purchase lego-something-or-other-game. Are you sure he's not already spending too much time on devices already?_ Woohoo, finally got the request! Unlock phone. Wait, WTH! Where's the authorisation dialog gone? Settings > Parental controls? Nope nothing there. Search > Parental Controls. Nothing there either. Sigh. Back to the kid's device again. Click Buy... again.\n\n_Enter Apple ID password_\n\nWhatever. Stupid long passwords.\n\n_Ask for your parent's approval_. Stab Ask. Kid now looking at you strangely because you're starting to mutter rude words under your breath.\n\nA message arrives on my phone: _Your iDevice-obsessed post-toddler wants to purchase lego-something-or-other-game._ Yes I know. It's **me** not the kid -- how's a child supposed to figure this out? Touch the dialog correctly this time.\n\nA message arrives on the kid's iPad: _The bossy parental unit has authorised your purchase._ Excellent. Hand back device to kid.\n\n\"Pa??\" iPad thrust back into my hands.\n\nWhat's the problem now? Oh, the buy button has turned into a get link. Only it doesn't look like a link at all. It's just the text `GET`. WTH? Where are the UI standards? Isn't this supposed to be a button??\n\n_Your purchase is downloading_. Finally. Mutter mutter Apple mutter.\n\n...5 mins passes...\n\n\"Pa?? I'm bored with this game. Can I try this one?\"\n\n\"Fine, okay\". Click Buy.\n\n_Enter Apple ID password_\n\n.\n\n.\n\n.\n\n![Angry, from Disney's Inside Out](https://jasonrbriggs.com/journal/2017/11/12/angry-inside-out.gif)", "content_html": "What's a nice way to give a kid a limited amount of spending freedom, and letting them buy some things without being able to decimate your credit card? iTunes Voucher -- seems reasonable right?
\nSo... redeeming voucher... Enter Apple ID password. Okay. Use camera to enter code. That's helpful. Please enter your credit card security code. Wait, what? Sigh. Fine.
\nHand iPad back to kid. \"Right, you can buy something now.\"
\n\"How about this one?\"
\n\"Nooo that's too expensive. Find another one.\"
\n\"What about this?\"
\n\"Yes okay, that works. You can click this Buy button here.\"
\n\"Pa??\" iPad thrust back into your hands.
\nEnter Apple ID password
\nSigh. Okay. Why the heck did I bother to add a nice long, secure password for his account?
\nAsk for your parent's approval. Click Ask... time passes... Nothing happened. Huh? Click Buy again.
\nEnter Apple ID password.
\nWTH? Just did that! For. The. Same. Game.
\nAsk for your parent's approval (they can also authorise on this device). Yes, but that defeats the purpose. The whole point was to let the kid buy a few things himself. Click Ask.
\nA message arrives on my phone: Your iDevice-obsessed post-toddler wants to purchase lego-something-or-other-game. Are you sure he's not already spending too much time on devices already? Woohoo, finally got the request! Unlock phone. Wait, WTH! Where's the authorisation dialog gone? Settings > Parental controls? Nope nothing there. Search > Parental Controls. Nothing there either. Sigh. Back to the kid's device again. Click Buy... again.
\nEnter Apple ID password
\nWhatever. Stupid long passwords.
\nAsk for your parent's approval. Stab Ask. Kid now looking at you strangely because you're starting to mutter rude words under your breath.
\nA message arrives on my phone: Your iDevice-obsessed post-toddler wants to purchase lego-something-or-other-game. Yes I know. It's me not the kid -- how's a child supposed to figure this out? Touch the dialog correctly this time.
\nA message arrives on the kid's iPad: The bossy parental unit has authorised your purchase. Excellent. Hand back device to kid.
\n\"Pa??\" iPad thrust back into my hands.
\nWhat's the problem now? Oh, the buy button has turned into a get link. Only it doesn't look like a link at all. It's just the text GET
. WTH? Where are the UI standards? Isn't this supposed to be a button??
Your purchase is downloading. Finally. Mutter mutter Apple mutter.
\n...5 mins passes...
\n\"Pa?? I'm bored with this game. Can I try this one?\"
\n\"Fine, okay\". Click Buy.
\nEnter Apple ID password
\n.
\n.
\n.
\n", "date_published": "2017-11-12T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/11/11/how-many-hours.html", "title": "How Many Hours", "url": "https://jasonrbriggs.com/journal/2017/11/11/how-many-hours.html", "content_text": "Xing Y writes:\n\n> _This is Xing Yanchao from the city of Qingdao, Shandong province, China, a big beautiful coastal city with 7 million citizens._\n> _I'm very interested in teaching kids to program, and plan to choose your book as the teaching material (In Chinese, ^\\_^)._\n> _The kids may be between 8~12, how many hours do you suggest for us to finish the whole book?_\n>\n> _Thank you in advance!_\n\nI think at least an hour a chapter for Part 1 of the book, but the chapters on functions, modules, classes and objects will probably take a bit longer. 12-15 hours is probably reasonable to cover most of Part 1 in a classroom setting, especially considering there should be a bit of time for kids to play around and try things for themselves, rather than following it exactly. Learn through play is important, particularly with a subject that can be pretty dry. Parts 2 and 3 are more difficult to estimate. I would actually suggest to just use Part 1 in the class, then let the kids come up with projects for themselves, and use the last two parts of the book as a reference (for example, let them create something for themselves, but use chapters 13-18 to figure out some of what they decide to do). Just a thought.", "content_html": "Xing Y writes:
\n\n\nThis is Xing Yanchao from the city of Qingdao, Shandong province, China, a big beautiful coastal city with 7 million citizens.\nI'm very interested in teaching kids to program, and plan to choose your book as the teaching material (In Chinese, ^_^).\nThe kids may be between 8~12, how many hours do you suggest for us to finish the whole book?
\nThank you in advance!
\n
I think at least an hour a chapter for Part 1 of the book, but the chapters on functions, modules, classes and objects will probably take a bit longer. 12-15 hours is probably reasonable to cover most of Part 1 in a classroom setting, especially considering there should be a bit of time for kids to play around and try things for themselves, rather than following it exactly. Learn through play is important, particularly with a subject that can be pretty dry. Parts 2 and 3 are more difficult to estimate. I would actually suggest to just use Part 1 in the class, then let the kids come up with projects for themselves, and use the last two parts of the book as a reference (for example, let them create something for themselves, but use chapters 13-18 to figure out some of what they decide to do). Just a thought.
", "date_published": "2017-11-11T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/10/10/multiplying-strings.html", "title": "Multiplying Strings", "url": "https://jasonrbriggs.com/journal/2017/10/10/multiplying-strings.html", "content_text": "Robin L writes (excerpted):\n\n> _I am trying to teach myself how to code and thought this was a good place to begin. I am having trouble with the \"multiplying_\n> _strings\" section. I don't know anyone else who codes so I am hoping that you are still available at this email. This is the_\n> _part about printing a letter in the shell. For some reason when I run mine the \"print()\" keeps actually printing \"()\"._\n>\n> _Can you please help me figure out what I am doing wrong?_\n\nThere's a pretty major difference between printing with older versions of Python (Python2.7 and earlier) and newer versions (Python3 and later). In Python2, `print` is a statement, which means this works fine:\n\n```python\nprint \"hi there\"\n```\n\nIf you try that in Python3, you'll get an error:\n\n```python\nprint \"hi there\"\n File \"Robin L writes (excerpted):
\n\n\nI am trying to teach myself how to code and thought this was a good place to begin. I am having trouble with the \"multiplying\nstrings\" section. I don't know anyone else who codes so I am hoping that you are still available at this email. This is the\npart about printing a letter in the shell. For some reason when I run mine the \"print()\" keeps actually printing \"()\".
\nCan you please help me figure out what I am doing wrong?
\n
There's a pretty major difference between printing with older versions of Python (Python2.7 and earlier) and newer versions (Python3 and later). In Python2, print
is a statement, which means this works fine:
print \"hi there\"
\nIf you try that in Python3, you'll get an error:
\nprint \"hi there\"\n File \"<stdin>\", line 1\n print \"hi there\"\n ^\nSyntaxError: Missing parentheses in call to 'print'
\nThat's because print
in Python3 is a function not a statement.
Why does that make a difference? In Python2, this code...
\nprint()
\n...is a print statement followed by an empty tuple. You're effectively telling Python to \"print this empty tuple\", and by quirk of the way the print statement works, you get ()
. The exact same code in Python3 is a function name (print) followed by an open bracket, no parameters, and a closing bracket. You're providing no parameters and the function prints nothing as a consequence. And that, basically, is the difference.
Cutting a long story short - all you're doing wrong is running an older version of Python. Check chapter one, and follow the instructions to install Python3, and the code will work as you expect.
", "date_published": "2017-10-10T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/07/16/stickman-refusing-to-move.html", "title": "Stickman Refusing To Move", "url": "https://jasonrbriggs.com/journal/2017/07/16/stickman-refusing-to-move.html", "content_text": "Haran R writes:\n\n> _I tried out the code for the two games and have successfully run the first game (bounce). The second game however did not run like_\n> _how i wished it to. I followed the book’s instructions to the letter, used the GIMP software to create the images, saved it in a_\n> _directory and saved the code in the same directory. The graphics came out fine but unfortunately I have not been able to get_\n> _the stickman to move. I have followed the coding in the book to the letter and have checked my code against the coding in the_\n> _book multiple times and i can see no mistakes._\n\nThe problem is with the indentation in your Stick Man class. If you look at the indentation of your code...\n\n[![indentation 1](https://jasonrbriggs.com/journal/2017/07/16/indentation1-small.png)](/journal/2017/07/16/indentation1.png)\n\nand then compare with mine...\n\n[![indentation 2](https://jasonrbriggs.com/journal/2017/07/16/indentation2-small.png)](/journal/2017/07/16/indentation2.png)\n\n...hopefully you'll see where you've gone wrong (if it's not immediately obvious, take a look at the vertical line coming down from the animate function in each of the code samples, and you'll see where the indentation isn't right). When I fixed the indentation on your code, it worked perfectly -- so you were almost there.\n\nHope that helps.", "content_html": "Haran R writes:
\n\n\nI tried out the code for the two games and have successfully run the first game (bounce). The second game however did not run like\nhow i wished it to. I followed the book’s instructions to the letter, used the GIMP software to create the images, saved it in a\ndirectory and saved the code in the same directory. The graphics came out fine but unfortunately I have not been able to get\nthe stickman to move. I have followed the coding in the book to the letter and have checked my code against the coding in the\nbook multiple times and i can see no mistakes.
\n
The problem is with the indentation in your Stick Man class. If you look at the indentation of your code...
\n\nand then compare with mine...
\n\n...hopefully you'll see where you've gone wrong (if it's not immediately obvious, take a look at the vertical line coming down from the animate function in each of the code samples, and you'll see where the indentation isn't right). When I fixed the indentation on your code, it worked perfectly -- so you were almost there.
\nHope that helps.
", "date_published": "2017-07-16T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/05/11/tcl-error.html", "title": "Tcl Error", "url": "https://jasonrbriggs.com/journal/2017/05/11/tcl-error.html", "content_text": "丁明 writes (edited for spelling):\n\n> _In your book <<python for kids>> chapter 13, when I run the program, the python shell has a error I can't understand._\n> _my python version 3.6.0. Thank you for your reply!!_\n\n![error.png](https://jasonrbriggs.com/journal/2017/05/11/error.png)\n\nI'm not sure if the Chinese edition has captured the text on page 199 of the English version of the book:\n\n> You may see error messages written to the shell when you close the\n> game window. This is because when you close the window, the code\n> is breaking out of the while loop, and Python is complaining about it.\n\nThe is exactly the error you are seeing when you run that code and then close the window. You are stopping (interrupting) Python while it is running the code, and an error message is displayed as a consequence.\n\nBasically, you can ignore the message, but if you want to know how to get rid of it for good, one option is to replace the loop at the bottom:\n\n```python\nwhile True:\n ball.draw()\n tk.update_idletasks()\n tk.update()\n time.sleep(0.01)\n```\n\n...with this...\n\n```python\ntry:\n\twhile True:\n\t ball.draw()\n\t tk.update_idletasks()\n\t tk.update()\n\t time.sleep(0.01)\nexcept TclError:\n\tpass\n```\n\nYou can find more about error handling here: [https://wiki.python.org/moin/HandlingExceptions](https://wiki.python.org/moin/HandlingExceptions)", "content_html": "丁明 writes (edited for spelling):
\n\n\n\nIn your book <<python for kids>> chapter 13, when I run the program, the python shell has a error I can't understand.\nmy python version 3.6.0. Thank you for your reply!!
\n
I'm not sure if the Chinese edition has captured the text on page 199 of the English version of the book:
\n\n\nYou may see error messages written to the shell when you close the\ngame window. This is because when you close the window, the code\nis breaking out of the while loop, and Python is complaining about it.
\n
The is exactly the error you are seeing when you run that code and then close the window. You are stopping (interrupting) Python while it is running the code, and an error message is displayed as a consequence.
\nBasically, you can ignore the message, but if you want to know how to get rid of it for good, one option is to replace the loop at the bottom:
\nwhile True:\n ball.draw()\n tk.update_idletasks()\n tk.update()\n time.sleep(0.01)
\n...with this...
\ntry:\n while True:\n ball.draw()\n tk.update_idletasks()\n tk.update()\n time.sleep(0.01)\nexcept TclError:\n pass
\nYou can find more about error handling here: https://wiki.python.org/moin/HandlingExceptions
", "date_published": "2017-05-11T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/04/08/windows-10.html", "title": "Windows 10", "url": "https://jasonrbriggs.com/journal/2017/04/08/windows-10.html", "content_text": "I've come across some uncorroborated reports that some of the instructions, or examples, in [Python for Kids](https://jasonrbriggs.com/python-for-kids) don't work with Windows 10. Uncorroborated because it's unfortunately nothing more than \"it don't work\". Not spectacularly useful, so I've finally gotten around to installing Windows 10 in VirtualBox to test this out.\n\nInstructions for Python installation remain pretty much the same, except that the latest version of Python is now 3.6, whereas on the last printing of PfK, it was 3.5. The results of installation aren't too dissimilar to Windows 7 either:\n\n[![windows-10 start menu](https://jasonrbriggs.com/journal/2017/04/08/windows-10-small.png)](/journal/2017/04/08/windows-10.png)\n\nI cherry-picked a few of the code samples at the beginning of the book to test, but wasn't expecting any of those to be a problem (they weren't), and then went through the more complicated code (turtle, tkinter) in the rest. Everything works as expected, except there is a little bit of graphical weirdness in the Bounce game (chapters 13, 14) where the ball seems to deform as it moves. I'm pretty certain this is an artifact of using Windows inside VirtualBox (I've never found animated graphics to work particularly well when you're in an OS inside an OS) - it's certainly not a problem in Linux or on a Mac. But interested to hear if anyone else has experienced the same issue on Windows:\n\n![Deformed ball](https://jasonrbriggs.com/journal/2017/04/08/deformed-ball.png)", "content_html": "I've come across some uncorroborated reports that some of the instructions, or examples, in Python for Kids don't work with Windows 10. Uncorroborated because it's unfortunately nothing more than \"it don't work\". Not spectacularly useful, so I've finally gotten around to installing Windows 10 in VirtualBox to test this out.
\nInstructions for Python installation remain pretty much the same, except that the latest version of Python is now 3.6, whereas on the last printing of PfK, it was 3.5. The results of installation aren't too dissimilar to Windows 7 either:
\n\nI cherry-picked a few of the code samples at the beginning of the book to test, but wasn't expecting any of those to be a problem (they weren't), and then went through the more complicated code (turtle, tkinter) in the rest. Everything works as expected, except there is a little bit of graphical weirdness in the Bounce game (chapters 13, 14) where the ball seems to deform as it moves. I'm pretty certain this is an artifact of using Windows inside VirtualBox (I've never found animated graphics to work particularly well when you're in an OS inside an OS) - it's certainly not a problem in Linux or on a Mac. But interested to hear if anyone else has experienced the same issue on Windows:
\n", "date_published": "2017-04-08T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/04/05/thats-pants.html", "title": "That's pants!", "url": "https://jasonrbriggs.com/journal/2017/04/05/thats-pants.html", "content_text": "Lee writes:\n\n> _I'm not fully understanding the HugeHairyPants program on pages 72-73 of Python For Kids. I initially thought that the loop would_\n> _produce \"huge huge hairy hairy pants pants,\" reasoning that the program would assign the first value to i, then the identical value_\n> _to j, and continue the loop._\n> _So why is the variable j assigned all of the values? My thought was that the program commands i to be the first variable ('huge'),_\n> _then stops there because the variable j is introduced next. Since there is no other variables after j, it then gets assigned every_\n> _variable. Is this correct? (It doesn't sound right to me, though.)_\n\nSo let's break the code down a bit more then. Here's the list...\n\n```python\nhugehairypants = ['huge', 'hairy', 'pants']\n```\n\n...and then the first two lines of the loop code:\n\n```python\nfor i in hugehairypants:\n\tprint(i)\n```\n\nIf we run this code right now we get:\n\n```python\nhuge\nhairy\npants\n```\n\nEach time the value in `i` is (effectively) replaced with the next value in the list (it's actually not quite as simple as that, but it can be easier to think of it that way when you start programming).\n\nIt's important to remember that every time we loop here, we're executing all the statements in the block of code - that's the indented part. And that's why if we look at the original example...\n\n```python\nfor i in hugehairypants:\n\tprint(i)\n\tfor j in hugehairypants:\n\t\tprint(j)\n```\n\n...it first executes `print(i)`, then it executes the second for-loop - that's looping over the `hugehairypants` list again, calling `print(j)` three times, then back to `print(i)` again, and so on. If we just look at the `print` statements Python is executing in these two loops, this is what it looks like:\n\n```python\nprint(i) # first for-loop - the value in i is now 'huge'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'\nprint(i) # first for-loop - the value in i is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'\nprint(i) # first for-loop - the value in i is now 'pants'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'\n```\n\nIf you need something more visual, I suggest drawing two rectangles on a piece of paper with 3 cells. Write the 3 values from the list in the cells (obviously it's not really two lists, but easier this way). Get two small coins; the first coin marks the value in `i`, the second coin marks the value in `j`. Work through the code as though you were running it yourself - move each coin to show how the value changes as we loop:\n\n![Visual guide](https://jasonrbriggs.com/journal/2017/04/05/pants.png)\n\n", "content_html": "Lee writes:
\n\n\nI'm not fully understanding the HugeHairyPants program on pages 72-73 of Python For Kids. I initially thought that the loop would\nproduce \"huge huge hairy hairy pants pants,\" reasoning that the program would assign the first value to i, then the identical value\nto j, and continue the loop.\nSo why is the variable j assigned all of the values? My thought was that the program commands i to be the first variable ('huge'),\nthen stops there because the variable j is introduced next. Since there is no other variables after j, it then gets assigned every\nvariable. Is this correct? (It doesn't sound right to me, though.)
\n
So let's break the code down a bit more then. Here's the list...
\nhugehairypants = ['huge', 'hairy', 'pants']
\n...and then the first two lines of the loop code:
\nfor i in hugehairypants:\n print(i)
\nIf we run this code right now we get:
\nhuge\nhairy\npants
\nEach time the value in i
is (effectively) replaced with the next value in the list (it's actually not quite as simple as that, but it can be easier to think of it that way when you start programming).
It's important to remember that every time we loop here, we're executing all the statements in the block of code - that's the indented part. And that's why if we look at the original example...
\nfor i in hugehairypants:\n print(i)\n for j in hugehairypants:\n print(j)
\n...it first executes print(i)
, then it executes the second for-loop - that's looping over the hugehairypants
list again, calling print(j)
three times, then back to print(i)
again, and so on. If we just look at the print
statements Python is executing in these two loops, this is what it looks like:
print(i) # first for-loop - the value in i is now 'huge'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'\nprint(i) # first for-loop - the value in i is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'\nprint(i) # first for-loop - the value in i is now 'pants'\nprint(j) # second for-loop - the value in j is now 'huge'\nprint(j) # second for-loop - the value in j is now 'hairy'\nprint(j) # second for-loop - the value in j is now 'pants'
\nIf you need something more visual, I suggest drawing two rectangles on a piece of paper with 3 cells. Write the 3 values from the list in the cells (obviously it's not really two lists, but easier this way). Get two small coins; the first coin marks the value in i
, the second coin marks the value in j
. Work through the code as though you were running it yourself - move each coin to show how the value changes as we loop:
Frankly this is bizarre, but if you're looking for Python for Kids, I suggest you don't buy on Amazon for the moment:
\n\nMuch as I'd like to be getting a cut of that price, I somehow doubt I'm getting anything -- and you're possibly getting a poor quality knock off, going by this:
\nhttps://twitter.com/billpollock/status/844030960333152256
\n(Some more discussion on Hacker News here: https://news.ycombinator.com/item?id=13924546 )
\nBarnes and Noble looks to be a safer option - and you can still buy directly from No Starch Press of course.
\nFurther update: Inc.com \"Amazon's Tepid Response to Counterfeiters Frustrates Sellers\"
", "date_published": "2017-03-22T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2017/01/18/askcolor.html", "title": "askcolor", "url": "https://jasonrbriggs.com/journal/2017/01/18/askcolor.html", "content_text": "Isai writes:\n\n> _I am having trouble with this code in page 176:_\n>\n> _from tkinter import *_\n> _colorchooser.askcolor()_\n>\n> _When I load it into IDLE, I get a blank canvas, and I can't close it, I have to restart the shell._\n>\n> _I have installed the proper ActiveTcl version (8.5), and no longer get the message giving me errors on startup._\n>\n> _When I run the previous code I was playing with (page 174), the canvas pops up and it all works again._\n> _Weirdly enough, the color picker pops up unprompted! I noticed that it does not bring up any buttons_\n> _that appear in your book: [OK] [Cancel]._\n\nThat's a bit of a gap in the book, because it doesn't make it clear that you need to create an instance of the top-level Tk widget first, **before** running that particular example (using `tk = Tk()`).\nSo the first time you run this function: `colorchooser.askcolor()`, it's hanging, waiting for something that isn't there yet. Then you run the code on the previous page (which does create the Tk object), and that's when you suddenly get a popup dialog with the colorchooser in it.\n\nSo the code should really look like this:\n\n```python\nfrom tkinter import *\nfrom tkinter import colorchooser\ntk = Tk()\ntk.update()\ncolorchooser.askcolor()\n```\n\nWhen you run that, you should then get the colorchooser dialog immediately.\n\n_Update #1: One step I missed, is a call to `tk.update()`, which forces tk to update the screen. Once that's executed, the chooser will appear. The example is updated above._\n\n_Update #2: On Windows you need to explicitly import `colorchooser` for the code to work properly (example updated again)._", "content_html": "Isai writes:
\n\n\nI am having trouble with this code in page 176:
\nfrom tkinter import *\ncolorchooser.askcolor()
\nWhen I load it into IDLE, I get a blank canvas, and I can't close it, I have to restart the shell.
\nI have installed the proper ActiveTcl version (8.5), and no longer get the message giving me errors on startup.
\nWhen I run the previous code I was playing with (page 174), the canvas pops up and it all works again.\nWeirdly enough, the color picker pops up unprompted! I noticed that it does not bring up any buttons\nthat appear in your book: [OK] [Cancel].
\n
That's a bit of a gap in the book, because it doesn't make it clear that you need to create an instance of the top-level Tk widget first, before running that particular example (using tk = Tk()
).\nSo the first time you run this function: colorchooser.askcolor()
, it's hanging, waiting for something that isn't there yet. Then you run the code on the previous page (which does create the Tk object), and that's when you suddenly get a popup dialog with the colorchooser in it.
So the code should really look like this:
\nfrom tkinter import *\nfrom tkinter import colorchooser\ntk = Tk()\ntk.update()\ncolorchooser.askcolor()
\nWhen you run that, you should then get the colorchooser dialog immediately.
\nUpdate #1: One step I missed, is a call to tk.update()
, which forces tk to update the screen. Once that's executed, the chooser will appear. The example is updated above.
Update #2: On Windows you need to explicitly import colorchooser
for the code to work properly (example updated again).
After something like 10 or more years completely ensconced in the Apple ecosystem, and now finding the price tag on the new MacBook Pros hard to justify, I'm looking around at alternatives. Before Apple, there was 7 - 8 (only occasionally fustrating) years of Linux in various flavours, so it makes sense to investigate linux-on-a-laptop options again. Looking at the Dell offerings though, it's clear they could learn from Apple's example -- at least in terms of pricing and consistency.
\nTo start with, a higher spec'd MacBook Pro, from the US website:
\n\nSo that's £2,267 (at time of writing) for a 15\" screen, i7 processor, 16GB of RAM and a 512GB solid state disk.
\nAnd for comparison, here's the same thing from the Apple UK and Apple NZ stores:
\n\nThe NZ price is roughly £2,637. Apart from the fact that the US price is a few hundred pounds cheaper, they're roughly consistent (in both price, and what you get for your money). VAT (in the UK) and GST (in NZ) probably account for, at least part of, the price variation.
\nHowever, compare this with Dell's Precision series laptops. The Precision 15 5000 series (again with 15\" screen, i7 processor and 512GB SSD) installed with Ubuntu Linux, comes in at a much more reasonable £1,483:
\n\nThe advantage of the Dell is that you can get a second 1TB HDD installed and the price is still less than the MacBook Pro (£1,558).
\nHowever, on the UK website, you can't order the additional hard drive, but the price is, at least, consistent (even if their website doesn't make it immediately obvious that you can order an i7 processor):
\n\n\nHowever, compare with Dell NZ:
\n\nThat's £4,095, give or take a few pence. A price variation I can only see justified, if Dell haven't figured out international shipping, and are flying the laptop into the country in a business class seat. In addition, not only do the websites vary slightly in each country, but the configuration options vary as well. In the US you can get the additional HDD, in the UK and NZ you cannot (perhaps some different regulations applying to the ex-US models, and the additional HDD doesn't fit?). In the UK, you can get a single 1x16GB memory unit installed, in the US and NZ stores you cannot.
\nConclusions? Apple: too expensive for a higher spec. Dell: either obscenely expensive, or inconsistent specifications, depending on which country I happen to be in (not to forget that if I want a bit of future proofing, it's difficult to be confident in the options). Other alternatives? A System76 Oryx Pro perhaps?
\nUpdate: Dell really is a bit of a mess. The NZ price for the XPS 15 (with ultra high def display) is only about £200 more than the UK price, but once again the configuration options look to be different between countries. Also with the XPS series, you don't have any option but to pay the Windows tax.
", "date_published": "2016-12-31T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/12/10/python-3-on-ubuntu-16.html", "title": "Python 3 on Ubuntu 16", "url": "https://jasonrbriggs.com/journal/2016/12/10/python-3-on-ubuntu-16.html", "content_text": "Roxana T writes (excerpted):\n\n> _I did look at the installation instructions in ch1 but still didn't work._\n> _I'm using Ubuntu and the built-in (is this the right word?) Python Version. It is I guess 2.7._\n> _I have the 3 version too, but I have to set it as default probably because when I launch Idle_\n> _I always get Python 2.7._\n\nSince I wrote Python for Kids, Ubuntu has changed their software installer and, at least in Ubuntu 16.04 when I try, I don't see a package installer for Idle (even though there used to be one available). So the best thing to do is to install it from the command line, by opening the Terminal and running:\n\n```bash\nsudo apt-get install idle3\n```\n\n(You'll need to enter the administrator password). You should see something similar to the following:\n\n```bash\nReading package lists... Done\nBuilding dependency tree\nReading state information... Done\nThe following packages were automatically installed and are no longer required:\n fonts-opensymbol fonts-stix libboost-date-time1.58.0\n libboost-iostreams1.58.0 libclucene-contribs1v5 libclucene-core1v5\n libcmis-0.5-5v5 libcolamd2.9.1 libeot0 libetonyek-0.1-1 libexttextcat-2.0-0\n libexttextcat-data liblangtag-common liblangtag1 libmhash2 libmwaw-0.3-3\n libmythes-1.2-0 libneon27-gnutls libodfgen-0.1-1 liborcus-0.10-0v5\n libraptor2-0 librasqal3 librdf0 librevenge-0.0-0 libsuitesparseconfig4.4.6\n libwps-0.4-4 libyajl2 lp-solve uno-libs3 ure\nUse 'apt autoremove' to remove them.\nThe following additional packages will be installed:\n blt idle-python3.5 python3-tk tk8.6-blt2.5\nSuggested packages:\n blt-demo tix python3-tk-dbg\nThe following NEW packages will be installed\n blt idle-python3.5 idle3 python3-tk tk8.6-blt2.5\n0 to upgrade, 5 to newly install, 0 to remove and 1 not to upgrade.\nNeed to get 647 kB of archives.\nAfter this operation, 2,345 kB of additional disk space will be used.\nDo you want to continue? [Y/n]\n```\n\nHit Y to continue, and after installation, you should be able to run `idle3` from the Terminal; and then, you won't get the funny compatibility errors you're been hitting with Python2. I also see Idle for Python 3.5 available from the launcher after installation, so you don't necessarily need to use the Terminal after that, if you don't want to.\n\n![idle in the launcher](https://jasonrbriggs.com/journal/2016/12/10/idle.png)\n", "content_html": "Roxana T writes (excerpted):
\n\n\nI did look at the installation instructions in ch1 but still didn't work.\nI'm using Ubuntu and the built-in (is this the right word?) Python Version. It is I guess 2.7.\nI have the 3 version too, but I have to set it as default probably because when I launch Idle\nI always get Python 2.7.
\n
Since I wrote Python for Kids, Ubuntu has changed their software installer and, at least in Ubuntu 16.04 when I try, I don't see a package installer for Idle (even though there used to be one available). So the best thing to do is to install it from the command line, by opening the Terminal and running:
\nsudo apt-get install idle3
\n(You'll need to enter the administrator password). You should see something similar to the following:
\nReading package lists... Done\nBuilding dependency tree\nReading state information... Done\nThe following packages were automatically installed and are no longer required:\n fonts-opensymbol fonts-stix libboost-date-time1.58.0\n libboost-iostreams1.58.0 libclucene-contribs1v5 libclucene-core1v5\n libcmis-0.5-5v5 libcolamd2.9.1 libeot0 libetonyek-0.1-1 libexttextcat-2.0-0\n libexttextcat-data liblangtag-common liblangtag1 libmhash2 libmwaw-0.3-3\n libmythes-1.2-0 libneon27-gnutls libodfgen-0.1-1 liborcus-0.10-0v5\n libraptor2-0 librasqal3 librdf0 librevenge-0.0-0 libsuitesparseconfig4.4.6\n libwps-0.4-4 libyajl2 lp-solve uno-libs3 ure\nUse 'apt autoremove' to remove them.\nThe following additional packages will be installed:\n blt idle-python3.5 python3-tk tk8.6-blt2.5\nSuggested packages:\n blt-demo tix python3-tk-dbg\nThe following NEW packages will be installed\n blt idle-python3.5 idle3 python3-tk tk8.6-blt2.5\n0 to upgrade, 5 to newly install, 0 to remove and 1 not to upgrade.\nNeed to get 647 kB of archives.\nAfter this operation, 2,345 kB of additional disk space will be used.\nDo you want to continue? [Y/n]
\nHit Y to continue, and after installation, you should be able to run idle3
from the Terminal; and then, you won't get the funny compatibility errors you're been hitting with Python2. I also see Idle for Python 3.5 available from the launcher after installation, so you don't necessarily need to use the Terminal after that, if you don't want to.
Drew M writes:
\n\n\nI have a question I am sure I don't know :) In tkinter I am creating a game and\ncan't figure out how to set dimensions for text. I need it on the middle.\nMy canvas is 1000 by 1000 so I divided in half. Which is of course 500.\nNow again, my question is how to put it there.
\n
Adding text to a canvas is straightforward (similar to adding any other item, such as a line, or a rectangle). You say \"middle\" and not \"center\", so I assume you don't want the text directly in the center of the canvas? I've defined a smaller canvas here, but the principle is the same:
\nfrom tkinter import *\ntk = Tk()\ncanvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)\ncanvas.create_text(50, 50, text='text')\ncanvas.pack()\ntk.update()
\n\nSo if you don't want the center, I'm guessing your problem is that this code...
\nfrom tkinter import *\ntk = Tk()\ncanvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)\ncanvas.create_text(50, 0, text='text')\ncanvas.pack()\ntk.update()
\n...(with coordinates of 50, 0) results in partially obscured text:
\n\nThe answer, is to use the named parameter anchor
in the create_text
function:
canvas.create_text(50, 0, text='text', anchor=N)
\nThe anchor
parameter controls the positioning of an item in terms of its coordinates. The default value is CENTER (so using this puts the center of the text at the coordinates (50, 0)
in the earlier example), but you can also use NW, N, NE (effectively top-left, top-middle, top-right), W, E (left and right), and SW, S, SE (bottom-left, bottom-middle, bottom-right). So N
puts the top and middle point of the text at the coordinates (50, 0)
, like so:
I hope that helps.
", "date_published": "2016-12-08T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/07/10/pfk-and-python-2.html", "title": "PfK and Python 2", "url": "https://jasonrbriggs.com/journal/2016/07/10/pfk-and-python-2.html", "content_text": "Tara P writes:\n\n> _I am going to be teaching Python 2 this coming school year and I am looking for a supplemental_\n> _learning tool and projects for myself and my students. Will your book Python for Kids work_\n> _with Python 2?_\n>\n> _I saw that it is recommended to use Python 3 however the curriculum I am teaching we are to use Python 2._\n> _I am not familiar enough with Python to know if the code language is different enough between them_\n> _where your book will not be useful for me?_\n\nThe short answer is no, it is not really designed to work with Python 2. The longer answer is that most of the code samples will work, but there are subtle differences between the two versions that may make it a little more difficult to get things working properly. There are some obvious differences (such as the `tkinter` module being called `Tkinter` in Python 2), which are straightforward to deal with and explain, but the more complicated the code, the more likely you are to hit issues that are less obvious, and as a consequence, cause frustrating errors for your students (I'm thinking more of the games in the later chapters, which aren't tested with Python2, and may either fail or hang).\n\nWhile moving from Python 2 to 3 is not enormously difficult, it's not necessarily something I would recommend for learners coming to a programming language for the first time.", "content_html": "Tara P writes:
\n\n\nI am going to be teaching Python 2 this coming school year and I am looking for a supplemental\nlearning tool and projects for myself and my students. Will your book Python for Kids work\nwith Python 2?
\nI saw that it is recommended to use Python 3 however the curriculum I am teaching we are to use Python 2.\nI am not familiar enough with Python to know if the code language is different enough between them\nwhere your book will not be useful for me?
\n
The short answer is no, it is not really designed to work with Python 2. The longer answer is that most of the code samples will work, but there are subtle differences between the two versions that may make it a little more difficult to get things working properly. There are some obvious differences (such as the tkinter
module being called Tkinter
in Python 2), which are straightforward to deal with and explain, but the more complicated the code, the more likely you are to hit issues that are less obvious, and as a consequence, cause frustrating errors for your students (I'm thinking more of the games in the later chapters, which aren't tested with Python2, and may either fail or hang).
While moving from Python 2 to 3 is not enormously difficult, it's not necessarily something I would recommend for learners coming to a programming language for the first time.
", "date_published": "2016-07-10T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/06/10/python3.5-on-macos.html", "title": "Python3.5 on macOS", "url": "https://jasonrbriggs.com/journal/2016/06/10/python3.5-on-macos.html", "content_text": "If you're installing Python3.5 on macOS, you don't need to follow the Automator instructions in Python for Kids any more. After installation, it's as simple as searching for IDLE in Spotlight (the magnifying glass in the top righthand side of the menu bar) and double-clicking on (usually) the top hit (\"IDLE - Python 3.5\").\n\nYou might still get an error message saying something like:\n\n> _The version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk for current information_\n\nTcl is a simple programming language and Tk is (sort of) a graphics library (more info here http://tldp.org/HOWTO/TclTk-HOWTO-3.html) -- the Tk graphics library is heavily used in later chapters of the book. If you happen to get the above error message, follow the instructions on the python.org website to install the correct version of ActiveTcl for the version of macOS you're running. This [post](https://jasonrbriggs.com/journal/2013/09/19/python-installation-confusion-on-mac-os-x.html) may also be of help.", "content_html": "If you're installing Python3.5 on macOS, you don't need to follow the Automator instructions in Python for Kids any more. After installation, it's as simple as searching for IDLE in Spotlight (the magnifying glass in the top righthand side of the menu bar) and double-clicking on (usually) the top hit (\"IDLE - Python 3.5\").
\nYou might still get an error message saying something like:
\n\n\nThe version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk for current information
\n
Tcl is a simple programming language and Tk is (sort of) a graphics library (more info here http://tldp.org/HOWTO/TclTk-HOWTO-3.html) -- the Tk graphics library is heavily used in later chapters of the book. If you happen to get the above error message, follow the instructions on the python.org website to install the correct version of ActiveTcl for the version of macOS you're running. This post may also be of help.
", "date_published": "2016-06-10T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/03/01/python-on-chromebook.html", "title": "Python on Chromebook", "url": "https://jasonrbriggs.com/journal/2016/03/01/python-on-chromebook.html", "content_text": "Cynthia B writes:\n\n> _I purchased your book Python for Kids so that my 11 year old daughter and I could start to learn code together._\n> _We are trying to install Python on her (lenovo 100S) chromebook to no avail._\n>\n> _We followed several prompts and purchased a python shell which has been installed but can not figure out where_\n> _to go from here, or if this will even be possible._\n> _Any advice?_\n\nAs far as I'm aware, the Python shell extensions available in the Chrome OS store aren't Python 3 compatible - so at least from a version perspective, that's a non-starter. Even if the version was correct, I suspect your mileage would probably vary with some of the later code examples in the book, using that sort of environment (not a fully fledged installation... again AFAIA).\n\nI don't have a Chromebook to try it out myself, but from a bit of searching, it looks like you can dual-boot Linux, and after that should be able to install anything you like ([http://stackoverflow.com/a/15261253/2685350](http://stackoverflow.com/a/15261253/2685350) - although Samsung-specific, I would hope the basic idea still applies).\n\nI've found some instructions on doing so at the following sites:\n[http://www.howtogeek.com/162120/how-to-install-ubuntu-linux-on-your-chromebook-with-crouton/](http://www.howtogeek.com/162120/how-to-install-ubuntu-linux-on-your-chromebook-with-crouton/)\n[http://lifehacker.com/how-to-install-linux-on-a-chromebook-and-unlock-its-ful-509039343](http://lifehacker.com/how-to-install-linux-on-a-chromebook-and-unlock-its-ful-509039343)\n[http://www.linux.com/learn/tutorials/764181-how-to-install-linux-on-an-acer-c720-chromebook](http://www.linux.com/learn/tutorials/764181-how-to-install-linux-on-an-acer-c720-chromebook)\n\n", "content_html": "Cynthia B writes:
\n\n\nI purchased your book Python for Kids so that my 11 year old daughter and I could start to learn code together.\nWe are trying to install Python on her (lenovo 100S) chromebook to no avail.
\nWe followed several prompts and purchased a python shell which has been installed but can not figure out where\nto go from here, or if this will even be possible.\nAny advice?
\n
As far as I'm aware, the Python shell extensions available in the Chrome OS store aren't Python 3 compatible - so at least from a version perspective, that's a non-starter. Even if the version was correct, I suspect your mileage would probably vary with some of the later code examples in the book, using that sort of environment (not a fully fledged installation... again AFAIA).
\nI don't have a Chromebook to try it out myself, but from a bit of searching, it looks like you can dual-boot Linux, and after that should be able to install anything you like (http://stackoverflow.com/a/15261253/2685350 - although Samsung-specific, I would hope the basic idea still applies).
\nI've found some instructions on doing so at the following sites:\nhttp://www.howtogeek.com/162120/how-to-install-ubuntu-linux-on-your-chromebook-with-crouton/\nhttp://lifehacker.com/how-to-install-linux-on-a-chromebook-and-unlock-its-ful-509039343\nhttp://www.linux.com/learn/tutorials/764181-how-to-install-linux-on-an-acer-c720-chromebook
", "date_published": "2016-03-01T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/02/21/pendrive.html", "title": "Pendrive", "url": "https://jasonrbriggs.com/journal/2016/02/21/pendrive.html", "content_text": "Kishore writes:\n\n> _I bought this great book \"python for kids\". I want to give it as a gift to kid in India._\n> _She doesn't have internet, but has a computer. What do I need to download and give in a_\n> _pendrive, so that she can finish the book without an internet connection._\n\nApart from the book itself, there's two extras to download: 1 - the solutions to all the programming challenges at the end of each chapter, and 2 - the code samples in the book (in case she has difficulty getting something to work).\n\nThe solutions are available from the publishers website here: [http://nostarch.com/pythonforkids](http://nostarch.com/pythonforkids).\nA zip file of all the code can be found here: [/python-for-kids/code.zip](https://jasonrbriggs.com/python-for-kids/code.zip).\n\nDepending on when you purchased the book, you might also want to take a copy of the [eratta](https://jasonrbriggs.com/python-for-kids/errata-up-to-apr2015.html). If it's a fairly recent reprint, there's no need. If the printing is before April 2015, then you should probably send that to her as well.\n\nYou didn't mention whether she already has Python installed, so if not, I suggest reading the first chapter yourself, so that you can include the right installation files for her OS.", "content_html": "Kishore writes:
\n\n\nI bought this great book \"python for kids\". I want to give it as a gift to kid in India.\nShe doesn't have internet, but has a computer. What do I need to download and give in a\npendrive, so that she can finish the book without an internet connection.
\n
Apart from the book itself, there's two extras to download: 1 - the solutions to all the programming challenges at the end of each chapter, and 2 - the code samples in the book (in case she has difficulty getting something to work).
\nThe solutions are available from the publishers website here: http://nostarch.com/pythonforkids.\nA zip file of all the code can be found here: /python-for-kids/code.zip.
\nDepending on when you purchased the book, you might also want to take a copy of the eratta. If it's a fairly recent reprint, there's no need. If the printing is before April 2015, then you should probably send that to her as well.
\nYou didn't mention whether she already has Python installed, so if not, I suggest reading the first chapter yourself, so that you can include the right installation files for her OS.
", "date_published": "2016-02-21T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/01/26/a-parameter-called-evt.html", "title": "A parameter called evt", "url": "https://jasonrbriggs.com/journal/2016/01/26/a-parameter-called-evt.html", "content_text": "Dudley B writes:\n\n> _I'm a Business Analyst trying to learn how to code. Luckily there's_\n> _Python, a suitable language for absolute beginners like me. Thank God_\n> _also for your book, Python for Kids. It's a great book which explains_\n> _Python fundamentals in a fun and easy way._\n> _In Chapter 14 of the book, page 208, there is a parameter called \"evt\":_\n>\n> _def turn\\_left(self, evt):_\n> _self.x = -2_\n> _def turn\\_right(self, evt):_\n> _self.x = 2_\n>\n> _I can't figure out what this parameter is for, and why it's there_\n> _since there is no value passed on to it. Please help me understand why_\n> _\"evt\" is needed for those functions._\n\nThe `evt` parameter isn't brilliantly explained in that chapter, now that I look back at it. If you go back to the section titled \"Making an object React to something\" in Chapter 12, there's a description there of _event bindings_. The function described takes a parameter called `event`. After you've \"told\" tkinter about the function (that's the binding part), when an event occurs (such as the mouse being moved, or keyboard being pressed) it calls that function with an object containing more information (such as what sort of event it was).\n\nThe parameter `evt` on page 208, is simply a shortened name for the parameter `event` mentioned in the earlier chapter. In fact, the name isn't important at all -- you could even call it `bob`, or `aardvark`, or anything else you like.\n\nBy the way, another way of thinking about the tkinter event binding is that it's like a contract between two people. Let's say between a surfer, and an old man living on a cliff above the sea. The surfer says to the old man, \"send me a message and let me know how high the surf is, whenever it changes\". The function is that contract, and the message about the surf is the parameter value.\n\nHopefully that helps.", "content_html": "Dudley B writes:
\n\n\nI'm a Business Analyst trying to learn how to code. Luckily there's\nPython, a suitable language for absolute beginners like me. Thank God\nalso for your book, Python for Kids. It's a great book which explains\nPython fundamentals in a fun and easy way.\nIn Chapter 14 of the book, page 208, there is a parameter called \"evt\":
\ndef turn_left(self, evt):\n self.x = -2\ndef turn_right(self, evt):\n self.x = 2
\nI can't figure out what this parameter is for, and why it's there\nsince there is no value passed on to it. Please help me understand why\n\"evt\" is needed for those functions.
\n
The evt
parameter isn't brilliantly explained in that chapter, now that I look back at it. If you go back to the section titled \"Making an object React to something\" in Chapter 12, there's a description there of event bindings. The function described takes a parameter called event
. After you've \"told\" tkinter about the function (that's the binding part), when an event occurs (such as the mouse being moved, or keyboard being pressed) it calls that function with an object containing more information (such as what sort of event it was).
The parameter evt
on page 208, is simply a shortened name for the parameter event
mentioned in the earlier chapter. In fact, the name isn't important at all -- you could even call it bob
, or aardvark
, or anything else you like.
By the way, another way of thinking about the tkinter event binding is that it's like a contract between two people. Let's say between a surfer, and an old man living on a cliff above the sea. The surfer says to the old man, \"send me a message and let me know how high the surf is, whenever it changes\". The function is that contract, and the message about the surf is the parameter value.
\nHopefully that helps.
", "date_published": "2016-01-26T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2016/01/03/stick-figure-error.html", "title": "Stick figure error", "url": "https://jasonrbriggs.com/journal/2016/01/03/stick-figure-error.html", "content_text": "WangXin writes (excerpted):\n\n> _I got a confusing error from the Python 3.4 (command line - 64 bit), it shows me this:_\n> _\"NameError: name 'collided\\_left is not defined'\" , I have checked my code over and over_\n> _again and I can't find the error. Could you help me to check my code when convenient?_\n\nThese sort of errors are (luckily) fairly easy to figure out. Any time you see an error about something\nnot being defined (and you're sure you've got the spelling correct) you can usually trace it back to a mistake in\nhow you have indented your code.\n\nHere's a relevant example from the book:\n\n[![indentation example](https://jasonrbriggs.com/journal/2016/01/03/indentation-small.png)](/journal/2016/01/03/indentation.png)\n\nIn this code, you can see that \"`class Coords`\" and \"`def within_x`\" have the same indentation (they're both at the left margin). Now if we look at the code you've entered, with visible whitespace, you can hopefully see the difference:\n\n[![incorrect indentation](https://jasonrbriggs.com/journal/2016/01/03/indentation-wrong-small.png)](/journal/2016/01/03/indentation-wrong.png)\n\nYour `within_x`, `within_y` and `collided_` functions are all indented to the same level as the `__init__` function of the Coords class -- in short, Python looks at them and thinks: \"those are indented the same as the init for the class, therefore they must be member functions of the same class\".\n\nSo, if you fix the indentation, I think you'll find your code suddenly works as expected:\n\n[![indentation corrected](https://jasonrbriggs.com/journal/2016/01/03/indentation-corrected-small.png)](/journal/2016/01/03/indentation-corrected.png)\n", "content_html": "WangXin writes (excerpted):
\n\n\nI got a confusing error from the Python 3.4 (command line - 64 bit), it shows me this:\n\"NameError: name 'collided_left is not defined'\" , I have checked my code over and over\nagain and I can't find the error. Could you help me to check my code when convenient?
\n
These sort of errors are (luckily) fairly easy to figure out. Any time you see an error about something\nnot being defined (and you're sure you've got the spelling correct) you can usually trace it back to a mistake in\nhow you have indented your code.
\nHere's a relevant example from the book:
\n\nIn this code, you can see that \"class Coords
\" and \"def within_x
\" have the same indentation (they're both at the left margin). Now if we look at the code you've entered, with visible whitespace, you can hopefully see the difference:
Your within_x
, within_y
and collided_
functions are all indented to the same level as the __init__
function of the Coords class -- in short, Python looks at them and thinks: \"those are indented the same as the init for the class, therefore they must be member functions of the same class\".
So, if you fix the indentation, I think you'll find your code suddenly works as expected:
\n", "date_published": "2016-01-03T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2015/08/26/tkinter-mainloop-issue-on-raspberry-pi.html", "title": "Tkinter mainloop issue on Raspberry Pi", "url": "https://jasonrbriggs.com/journal/2015/08/26/tkinter-mainloop-issue-on-raspberry-pi.html", "content_text": "Martin writes:\n\n> _First of all thank you for writing \"Python for Kids\". It's a great book and offers \"instant gratification\"._\n> _My 8-year-old is already hacking his way through the pages on his brand new Raspberry Pi._\n>\n> _He (we) ran into a bit of trouble when we started playing with Tkinter._\n>\n> _Your initial examples don't ever call mainloop() or update(). Turns out, on the Raspi,_\n> _in IDLE, those examples don't work as expected - nothing appears on screen. Until you run mainloop() that is._ \n> \n>\n> _If you run a pure python3 interpreter inside a shell window, your examples work._\n> _[They will also not work on Windows inside a Python 2.7.10 IDLE.]_\n>\n> _Could you throw any light on why things work without calling mainloop() on some setups but not on others?_\n\nTurns out that trying to reproduce your problem - without having a RPi to hand - was a lot more difficult than I expected. Even after getting [Raspbian](http://www.raspbian.org) going with [QEMU](http://wiki.qemu.org/Main_Page), I couldn't get a menu to display so that I could run IDLE (solution: create an empty file, and from the file's context menu you can then access the Terminal). However, when I ran IDLE, it only worked in \"no subprocess mode\" (see the first chapter of the book). If I run without specifying `-n`, I get the following error:\n\n[![qemu error](https://jasonrbriggs.com/journal/2015/08/26/qemu-error-small.png)](/journal/2015/08/26/qemu-error.png)\n\nOnly after going through the above, did I remember that there was an issue with IDLE & tkinter on Python 3.2 (when running without `-n`). And sure enough, when running with 3.2 on my PC, I get the exact same problem (it doesn't occur with later versions of Python).\n\nBest thing you can do, is to run IDLE with the `-n` flag - the turtle/tkinter code you run will be more stable as a consequence (and there's no need to call `mainloop`).\n\n(PS. as for Python 2.7.x, many of the code samples won't work - the book is only intended to be used with Python 3.x)", "content_html": "Martin writes:
\n\n\nFirst of all thank you for writing \"Python for Kids\". It's a great book and offers \"instant gratification\".\nMy 8-year-old is already hacking his way through the pages on his brand new Raspberry Pi.
\nHe (we) ran into a bit of trouble when we started playing with Tkinter.
\nYour initial examples don't ever call mainloop() or update(). Turns out, on the Raspi,\nin IDLE, those examples don't work as expected - nothing appears on screen. Until you run mainloop() that is.
\n
\nIf you run a pure python3 interpreter inside a shell window, your examples work.\n[They will also not work on Windows inside a Python 2.7.10 IDLE.]
\nCould you throw any light on why things work without calling mainloop() on some setups but not on others?
\n
Turns out that trying to reproduce your problem - without having a RPi to hand - was a lot more difficult than I expected. Even after getting Raspbian going with QEMU, I couldn't get a menu to display so that I could run IDLE (solution: create an empty file, and from the file's context menu you can then access the Terminal). However, when I ran IDLE, it only worked in \"no subprocess mode\" (see the first chapter of the book). If I run without specifying -n
, I get the following error:
Only after going through the above, did I remember that there was an issue with IDLE & tkinter on Python 3.2 (when running without -n
). And sure enough, when running with 3.2 on my PC, I get the exact same problem (it doesn't occur with later versions of Python).
Best thing you can do, is to run IDLE with the -n
flag - the turtle/tkinter code you run will be more stable as a consequence (and there's no need to call mainloop
).
(PS. as for Python 2.7.x, many of the code samples won't work - the book is only intended to be used with Python 3.x)
", "date_published": "2015-08-26T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2015/08/21/python-3.5beta-issues-on-windows.html", "title": "Python 3.5 beta issue on Windows", "url": "https://jasonrbriggs.com/journal/2015/08/21/python-3.5beta-issues-on-windows.html", "content_text": "Tony writes:\n\n> _I have installed Python 3.5.0b3, and when I tried to make the shortcut, it looked very different from the book's_\n> _examples and I did not get the toolbar with \"File\", \"Edit\", \"Options\", etc. on the top. Please tell me how to correctly complete_\n> _the installation process. Thank you, and I hope to hear back._\n\nI'm not sure exactly what error you're getting, but I would suggest that while learning programming, you should probably use the latest *release* version of Python, rather than the *beta*. So at time of writing, that's [version 3.4.3](https://www.python.org/downloads/release/python-343/).\n\nI do know of one problem with 3.5, where you need to move the DLL found in directory *c:\\Python35\\DLLs\\Microsoft.VC140.CRT*, up one level (to directory *c:\\Python35\\DLLs*), in order to get tkinter working -- which I guess could be part of your problem (as detailed here: [https://bugs.python.org/issue24847](https://bugs.python.org/issue24847)).\n\nSo that's simply moving the file here:\n\n[![microsoft.vc140.crt file - original location](https://jasonrbriggs.com/journal/2015/08/21/microsoft-dll-file1-small.png)](/journal/2015/08/21/microsoft-dll-file1.png)\n\nto here:\n\n[![microsoft.vc140.crt file - new location](https://jasonrbriggs.com/journal/2015/08/21/microsoft-dll-file2-small.png)](/journal/2015/08/21/microsoft-dll-file2.png)\n\n**NOTE: this is no longer required for the release version of 3.5 (it was only necessary for the beta versions)**", "content_html": "Tony writes:
\n\n\nI have installed Python 3.5.0b3, and when I tried to make the shortcut, it looked very different from the book's\nexamples and I did not get the toolbar with \"File\", \"Edit\", \"Options\", etc. on the top. Please tell me how to correctly complete\nthe installation process. Thank you, and I hope to hear back.
\n
I'm not sure exactly what error you're getting, but I would suggest that while learning programming, you should probably use the latest release version of Python, rather than the beta. So at time of writing, that's version 3.4.3.
\nI do know of one problem with 3.5, where you need to move the DLL found in directory c:\\Python35\\DLLs\\Microsoft.VC140.CRT, up one level (to directory c:\\Python35\\DLLs), in order to get tkinter working -- which I guess could be part of your problem (as detailed here: https://bugs.python.org/issue24847).
\nSo that's simply moving the file here:
\n\nto here:
\n\nNOTE: this is no longer required for the release version of 3.5 (it was only necessary for the beta versions)
", "date_published": "2015-08-21T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2015/08/14/syntax-error-in-myletter.py.html", "title": "Syntax error in myletter.py", "url": "https://jasonrbriggs.com/journal/2015/08/14/syntax-error-in-myletter.py.html", "content_text": "> _I have recently bought your book, Python For Kids and I think it's great and easy to understand_\n> _except for one small thing._\n>\n> _It tells me to put this into the Shell:_\n>\n> _spaces = ' ' * 25_ \n> _print('%s 12 Butts wynd' % spaces)_ \n> _print('%s Twinklebottom heath') % spaces)_ \n> _print()_ \n> _print()_ \n> _print('Dear Sir')_ \n> (excerpted)\n>\n> _I do what it says, I click run module, but I get this error:_ \n> ![error in editor window](https://jasonrbriggs.com/journal/2015/08/14/myletter-error.png) \n> _I'm new to this, so I probably made some extremely stupid mistake, and i'm sorry if this is the wrong place to ask._\n\nWhen I enter your code, I get the same error. But once I click OK, in the editor window I see the following: \n![error in editor window](https://jasonrbriggs.com/journal/2015/08/14/myletter-error-window.png) \nThat red highlight, on the third line down, shows you on where the error has occurred - and hopefully gives an idea about what might have gone wrong. In this case, Python isn't expecting a bracket at the end, because you've got one earlier in the line:\n`print('%s Twinklebottom heath') % spaces)`.\nIf you remove that bracket -- it should look like this `print('%s Twinklebottom heath' % spaces)` -- you'll find the program runs as expected.\n", "content_html": "\n\nI have recently bought your book, Python For Kids and I think it's great and easy to understand\nexcept for one small thing.
\nIt tells me to put this into the Shell:
\nspaces = ' ' * 25
\n
\nprint('%s 12 Butts wynd' % spaces)
\nprint('%s Twinklebottom heath') % spaces)
\nprint()
\nprint()
\nprint('Dear Sir')
\n(excerpted)I do what it says, I click run module, but I get this error:
\n
\n
\nI'm new to this, so I probably made some extremely stupid mistake, and i'm sorry if this is the wrong place to ask.
When I enter your code, I get the same error. But once I click OK, in the editor window I see the following:
\n
\nThat red highlight, on the third line down, shows you on where the error has occurred - and hopefully gives an idea about what might have gone wrong. In this case, Python isn't expecting a bracket at the end, because you've got one earlier in the line:\nprint('%s Twinklebottom heath') % spaces)
.\nIf you remove that bracket -- it should look like this print('%s Twinklebottom heath' % spaces)
-- you'll find the program runs as expected.
Sandy S writes:
\n\n\nI just purchased 3 copies of \"Python for Kids\" so that my 2 sons and I can begin our quest!\nAnyway I hate to bug you with this but we just downloaded the latest version of the Python suite\nand the –n switch for IDLE startup has a message about \"being deprecated since version 3.4\".\nIs there another startup scheme that we should use instead?\nAlso what do you recommend, in addition to the fine book, to enhance the learning process?\nMy sons are middle-school age and very math/science savvy. I have a hardware engineering background\nbut no programming to speak of.
\n
The -n switch is deprecated, but not yet removed. So it still works fine with that switch for the moment. I did see some discussion about it on one of the Python mailing lists (forget which now) but I don’t think there was a conclusion about what happens in the future with something like IDLE and the use of tkinter (perhaps someone else reads this and lets me know - in which case, I'll post their message here). In any case, safe to use.
\nIn terms of enhancing the learning process, I'd say once they've gone through the book (at least covered the basics of programming) picking a project is a good idea. Static learning is fine up to a point (even working through examples in the book), but what really cements the learning process is finding something you actually want to work on. It doesn't matter what sort of project, game or otherwise. As long as it's something your boys are interested in (also think about things like the raspberry pi and robotics and so on — since you've got a hardware background that'll be a useful crossover).
\nHope that helps.
", "date_published": "2015-07-12T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2015/02/26/problem-with-if-statements.html", "title": "Problem with IF statements", "url": "https://jasonrbriggs.com/journal/2015/02/26/problem-with-if-statements.html", "content_text": "Art S writes (excerpted):\n\n> _First, let me say that I am having a great time learning Python from Python for Kids, even though I am just_\n> _a kid at heart. I'm an old, old guy (I'll be 52 in April), but my students keep me young - I've been_\n> _teaching high school mathematics for 25 years, and I am finally getting around to checking \"Learn Python\"_\n> _off of my to-do list._\n>\n> _Here's the problem. All of my code has been running fine through IDLE until I got to the chapter on IF_\n> _statements. When I typed into IDLE the first example from Chapter 5, page 54, nothing happened - the_\n> _string 'You are too old!' (coincidence?) was not returned. All of the other examples involving IF's lead_\n> _to the same result - nothing._\n>\n> ![if-statement](https://jasonrbriggs.com/journal/2015/02/26/if-statement.png)\n>\n>\n> _I thought I would give it one more try, just to be sure. When I did, I accidentally hit enter twice,_\n> _and the desired output appeared. I feel good that it worked, but why should I have to hit enter twice?_\n\nSo there's nothing you're actually doing wrong here. When you hit enter after typing the second line (the `print` part), Python is just waiting for the next statement in that block of code. Python uses white-space for the program structure, so the only way it knows you've actually finished that particular block of code, is when you hit enter again on the next line. So Python only runs the code once you've actually said you've finished... and the way you say you're finished, in this case, is to hit enter on an empty line.\n\n.....\n\nMiquel C writes:\n\n> _Do you know where to learn Python? I've been searching and I've only found Codecademy. I'd be very happy_\n> _if you know where to go from Python For Kids._\n> _All kind of learning would be great._\n>\n> _I also downloaded an IRC bot, and I've translated it to my language. I've been looking the code and_\n> _learning a bit._\n\nOnce you've mastered the basics of programming, my suggestion would be to find a small project to work on. Rather than looking at other people's code, or reading another, more advanced book, try creating your own version of an application you're interested in. It should be challenging, but not impossible. For example, when I was younger, I learned a new programming language by creating my own version of [Tetris](http://en.wikipedia.org/wiki/Tetris). You'll hit problems you don't know how to solve, so you'll end up reading the Python documentation, or googling to find the answers, or asking questions on sites like [StackOverflow](http://stackoverflow.com). But that's the one of the best ways to carry on learning (in my opinion).", "content_html": "Art S writes (excerpted):
\n\n\nFirst, let me say that I am having a great time learning Python from Python for Kids, even though I am just\na kid at heart. I'm an old, old guy (I'll be 52 in April), but my students keep me young - I've been\nteaching high school mathematics for 25 years, and I am finally getting around to checking \"Learn Python\"\noff of my to-do list.
\nHere's the problem. All of my code has been running fine through IDLE until I got to the chapter on IF\nstatements. When I typed into IDLE the first example from Chapter 5, page 54, nothing happened - the\nstring 'You are too old!' (coincidence?) was not returned. All of the other examples involving IF's lead\nto the same result - nothing.
\n\nI thought I would give it one more try, just to be sure. When I did, I accidentally hit enter twice,\nand the desired output appeared. I feel good that it worked, but why should I have to hit enter twice?
\n
So there's nothing you're actually doing wrong here. When you hit enter after typing the second line (the print
part), Python is just waiting for the next statement in that block of code. Python uses white-space for the program structure, so the only way it knows you've actually finished that particular block of code, is when you hit enter again on the next line. So Python only runs the code once you've actually said you've finished... and the way you say you're finished, in this case, is to hit enter on an empty line.
.....
\nMiquel C writes:
\n\n\nDo you know where to learn Python? I've been searching and I've only found Codecademy. I'd be very happy\nif you know where to go from Python For Kids.\nAll kind of learning would be great.
\nI also downloaded an IRC bot, and I've translated it to my language. I've been looking the code and\nlearning a bit.
\n
Once you've mastered the basics of programming, my suggestion would be to find a small project to work on. Rather than looking at other people's code, or reading another, more advanced book, try creating your own version of an application you're interested in. It should be challenging, but not impossible. For example, when I was younger, I learned a new programming language by creating my own version of Tetris. You'll hit problems you don't know how to solve, so you'll end up reading the Python documentation, or googling to find the answers, or asking questions on sites like StackOverflow. But that's the one of the best ways to carry on learning (in my opinion).
", "date_published": "2015-02-26T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2015/01/10/error-opening-idle-on-mac-os-x-10.6.html", "title": "Error opening IDLE on Mac OS X 10.6", "url": "https://jasonrbriggs.com/journal/2015/01/10/error-opening-idle-on-mac-os-x-10.6.html", "content_text": "Lucas writes (excerpted):\n\n> _When I try to open IDLE as instructed on page 11 I get an error message._\n\nLucas writes (excerpted):
\n\n\nWhen I try to open IDLE as instructed on page 11 I get an error message.
\n
\n\nAny suggestions?
\n
It depends on which version of Python you're running, but if you've installed the latest (3.4.2), then instead of putting the following in Automator:
\nopen -a \"/Applications/Python 3.4/IDLE.app\" --args -n
\nTry putting this instead:
\n/Library/Frameworks/Python.framework/Versions/3.4/bin/idle3.4 -n
\nThe reason the text in the book doesn't work is a difference between Automator in versions of OS X prior to 10.7 (I believe 10.7, anyway) and later versions of the operating system.
", "date_published": "2015-01-10T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/12/28/incrementing-photo-filenames.html", "title": "Incrementing photo filenames", "url": "https://jasonrbriggs.com/journal/2014/12/28/incrementing-photo-filenames.html", "content_text": "Emmeline writes:\n\n> _I'm twelve and I recently got a raspberry Pi camera module. I really wanted to do stop animation with it but,_\n> _when I used Tkinter to make a button it would take a picture when I pressed it and save it as I specified._\n> _The problem is if I wanted to use the button again it deleted the old image ex image.jpg and replaced it_\n> _with a new image (image.jpg). Do you have any suggestions of how to change the code so it will name the photos_\n> _numerically. Ex image1.jpg then image2.jpg. I'm doing all this in idle3._\n> _Thanks a lot for the book. \"Python for kids\" is great._\n\nGlad you like the book.\n\nThere's a few ways you can change your code to have an incrementing filename. You could write a class, which uses a variable to store the current number. The class would have a function which increments the variable and returns the value. Something like this would work:\n\n```python\n>>> class Counter:\n... def __init__(self):\n... self.counter = 0\n... def next(self):\n... self.counter += 1\n... return self.counter\n...\n```\n\nYou could use the class by creating an object like this:\n\n```python\n>>> c = Counter()\n>>> c.next()\n1\n>>> c.next()\n2\n```\n\nYou could then create a function to return a unique image name each time it's called:\n\n```python\nc = Counter()\n\ndef get_image_name():\n return 'image%s.jpg' % c.next()\n```\n\nYou could also just adapt the code above to create a class which returns unique image names:\n\n```python\n>>> class ImageNames:\n... def __init__(self):\n... self.counter = 0\n... def next_image_name(self):\n... self.counter += 1\n... return 'image%s.jpg' % self.counter\n...\n>>> im = ImageNames()\n>>> im.next_image_name()\n'image1.jpg'\n>>> im.next_image_name()\n'image2.jpg'\n```\n\nBy the way, you can find more about embedding values in strings in Chapter 3, and classes and objects in Chapter in Chapter 8.\n\nHope that helps.\n\n", "content_html": "Emmeline writes:
\n\n\nI'm twelve and I recently got a raspberry Pi camera module. I really wanted to do stop animation with it but,\nwhen I used Tkinter to make a button it would take a picture when I pressed it and save it as I specified.\nThe problem is if I wanted to use the button again it deleted the old image ex image.jpg and replaced it\nwith a new image (image.jpg). Do you have any suggestions of how to change the code so it will name the photos\nnumerically. Ex image1.jpg then image2.jpg. I'm doing all this in idle3.\nThanks a lot for the book. \"Python for kids\" is great.
\n
Glad you like the book.
\nThere's a few ways you can change your code to have an incrementing filename. You could write a class, which uses a variable to store the current number. The class would have a function which increments the variable and returns the value. Something like this would work:
\n>>> class Counter:\n... def __init__(self):\n... self.counter = 0\n... def next(self):\n... self.counter += 1\n... return self.counter\n...
\nYou could use the class by creating an object like this:
\n>>> c = Counter()\n>>> c.next()\n1\n>>> c.next()\n2
\nYou could then create a function to return a unique image name each time it's called:
\nc = Counter()\n\ndef get_image_name():\n return 'image%s.jpg' % c.next()
\nYou could also just adapt the code above to create a class which returns unique image names:
\n>>> class ImageNames:\n... def __init__(self):\n... self.counter = 0\n... def next_image_name(self):\n... self.counter += 1\n... return 'image%s.jpg' % self.counter\n...\n>>> im = ImageNames()\n>>> im.next_image_name()\n'image1.jpg'\n>>> im.next_image_name()\n'image2.jpg'
\nBy the way, you can find more about embedding values in strings in Chapter 3, and classes and objects in Chapter in Chapter 8.
\nHope that helps.
", "date_published": "2014-12-28T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/10/22/well-done-amazon---terrible-ux.html", "title": "Well done Amazon - truly awful UX", "url": "https://jasonrbriggs.com/journal/2014/10/22/well-done-amazon---terrible-ux.html", "content_text": "How to ensure that your customers never, ever... *ever* want to sign up for Prime... *ever*:\n\n_Step 1._ \nPrompt user to sign up for Amazon Prime while processing their order.\n\n_Step 2._ \nCustomer clicks \"No Thanks\" (because customer was previously signed up for Prime and decided they didn't want to pay for it - so of course you should ask again and again... and again)\n\n_Step 3._ \nDisplay final checkout page to customer and automatically select the paid shipping option (okay fine, that's fairly normal)\n\n_Step 4._ \nDisplay popup window to customer asking them to sign up for Amazon Prime *again* (did I mention *again*?), only this time position the *Sign up* link in the exact same position that that the radio button for \"Free Super Saver Delivery\" is displayed (because you know that's the button they're probably going to select). Better yet, you should time the display of this popup so that by the time they've moved the mouse cursor into place, customer is clicking on said radio button at the very moment the popup appears.\n\n_Step 5._ \nBy no means should you ask for confirmation before signing the customer up, when they do mistakenly click.\n\nFrankly, don't know whether it was just exceptionally poor, or whether it was nefarious UX design to get people on Prime, but it's a really, really good way to annoy your customers. Or at least this customer.", "content_html": "How to ensure that your customers never, ever... ever want to sign up for Prime... ever:
\nStep 1.
\nPrompt user to sign up for Amazon Prime while processing their order.
Step 2.
\nCustomer clicks \"No Thanks\" (because customer was previously signed up for Prime and decided they didn't want to pay for it - so of course you should ask again and again... and again)
Step 3.
\nDisplay final checkout page to customer and automatically select the paid shipping option (okay fine, that's fairly normal)
Step 4.
\nDisplay popup window to customer asking them to sign up for Amazon Prime again (did I mention again?), only this time position the Sign up link in the exact same position that that the radio button for \"Free Super Saver Delivery\" is displayed (because you know that's the button they're probably going to select). Better yet, you should time the display of this popup so that by the time they've moved the mouse cursor into place, customer is clicking on said radio button at the very moment the popup appears.
Step 5.
\nBy no means should you ask for confirmation before signing the customer up, when they do mistakenly click.
Frankly, don't know whether it was just exceptionally poor, or whether it was nefarious UX design to get people on Prime, but it's a really, really good way to annoy your customers. Or at least this customer.
", "date_published": "2014-10-22T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/09/08/multiple-statements-found.html", "title": "Multiple statements found", "url": "https://jasonrbriggs.com/journal/2014/09/08/multiple-statements-found.html", "content_text": "Arijjan V writes (excerpted):\n\n> _When I enter code into the compiler I continue to get multiple statement error messages._\n> _Even if I copy the code from the book._\n>\n> _I use Idle 34 on windows professional 7. This is what I typed into the Idle Shell._\n>\n> _found\\_coins = 20_\n> _magic\\_coins = 70_\n> _stolen\\_coins = 3_\n> _coins = found\\_coins_\n> _for week in range(1, 53):_\n> _coins = coins + magic\\_coins - stolen\\_coins_\n> _print('Week %s = %s' % (week, coins))_\n> _\\*\\*Click Enter\\*\\*_\n> _SyntaxError: multiple statements found while compiling a single statement_\n>\n> _I searched online but it's not an indent error. I'd appreciate any help._\n\nTo be honest, I'm not quite sure how you managed to get that error when __typing__ the code into IDLE - the only way I can get it to happen, is if I copy-and-paste directly into the Shell:\n\nArijjan V writes (excerpted):
\n\n\nWhen I enter code into the compiler I continue to get multiple statement error messages.\nEven if I copy the code from the book.
\nI use Idle 34 on windows professional 7. This is what I typed into the Idle Shell.
\nfound_coins = 20\nmagic_coins = 70\nstolen_coins = 3\ncoins = found_coins\nfor week in range(1, 53):\n coins = coins + magic_coins - stolen_coins\n print('Week %s = %s' % (week, coins))\n**Click Enter**\nSyntaxError: multiple statements found while compiling a single statement
\nI searched online but it's not an indent error. I'd appreciate any help.
\n
To be honest, I'm not quite sure how you managed to get that error when typing the code into IDLE - the only way I can get it to happen, is if I copy-and-paste directly into the Shell:
\nThe reason being is that you can only copy-and-paste line-by-line into the Shell window (a quirk of the way it works). What you should actually be entering looks like this:
\nIf you want to paste in a large chunk of code, then click File
, then New File
, then paste the code, and save the file before trying to run it:
If you can reproduce the problem when typing in the code, send a screenshot (take it after entering a few lines) -- I'd be interested to see if it's obvious from the screenshot what the cause is...
", "date_published": "2014-09-08T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/09/03/restarting-the-game.html", "title": "Restarting the game", "url": "https://jasonrbriggs.com/journal/2014/09/03/restarting-the-game.html", "content_text": "Lyna M writes (excerpted):\n\n> _I bought your book Python for Kids with the intention to teach my son Python later on but have now been_\n> _using it myself to learn Python as I find your book to be quite comprehensive even if it was 'for kids'._\n>\n> _I've been doing the Bounce tutorial and would like to find a way to add a restart button so that each time_\n> _the game ends, the player can restart the game if they want to._\n>\n> _I've applied the codes for Game Over but would like to add a restart button after that._\n>\n> _if ball.hit\\_bottom == True:_ \n> _ time.sleep_ \n> _ canvas.itemconfig(game\\_over\\_text, state='normal')_ \n> _ btn = Button(tk, text=\"Click to Restart Game\")_ \n> _ btn.pack()_ \n> _tk.update\\_idletasks()_ \n> _tk.update()_ \n> _time.sleep(0.01)_ \n>\n> _tk = Tk()_ \n> _btn = Button(tk, text=\"Click to Restart Game\")_ \n> _btn.pack()_ \n>\n> _How to tie in the button so that it restarts the game when clicked? I've been trying out codes from_\n> _forums and blogs but they don't seem to work or are too hard to understand._\n\nThere's a few ways you can handle the restart. If you look at the programming puzzles in Chapter 14, the first challenge is to delay the game start using the `Lyna M writes (excerpted):
\n\n\nI bought your book Python for Kids with the intention to teach my son Python later on but have now been\nusing it myself to learn Python as I find your book to be quite comprehensive even if it was 'for kids'.
\nI've been doing the Bounce tutorial and would like to find a way to add a restart button so that each time\nthe game ends, the player can restart the game if they want to.
\nI've applied the codes for Game Over but would like to add a restart button after that.
\nif ball.hit_bottom == True:
\n
\n time.sleep
\n canvas.itemconfig(game_over_text, state='normal')
\n btn = Button(tk, text=\"Click to Restart Game\")
\n btn.pack()
\ntk.update_idletasks()
\ntk.update()
\ntime.sleep(0.01)tk = Tk()
\n
\nbtn = Button(tk, text=\"Click to Restart Game\")
\nbtn.pack()How to tie in the button so that it restarts the game when clicked? I've been trying out codes from\nforums and blogs but they don't seem to work or are too hard to understand.
\n
There's a few ways you can handle the restart. If you look at the programming puzzles in Chapter 14, the first challenge is to delay the game start using the <Button-1>
binding; to tie a mouse button click to a function which then starts the game. You could adapt that function to also restart the game once it's over. That's probably the most seamless approach.
If you really want to use a button, you need a way to add it just once -- because where you've added it (inside the loop), you'll get one button added to the window for every iteration of the loop. After the loop finishes isn't really the right place either.
\nFirst of all you'll need a Game class which will tie all the game objects together. Basically the new class would have object variables to 'store' the paddle, the ball, the score, the game-over-text, and also your restart button (initially the restart button variable would be set to None). So rather than adding the button inside the if-statement, you might do something like this:
\n game = Game(canvas, paddle, ball, score, game_over_text)\n\n --- ✂ ---\n\n while 1:\n\n --- ✂ ---\n\n if ball.hit_bottom == True:\n time.sleep(1)\n canvas.itemconfig(game_over_text, \n state='normal')\n if game.restart_button is None:\n game.add_restart()
\nIn the above code, we check if the value of the game variable restart_button
is None (in other words, the button is not currently displayed), we call a function add_restart
- so that fixes the problem of adding the button more than once. Here's the code for adding the button:
class Game:\n\n --- ✂ ---\n\n def add_restart(self):\n self.restart_button = Button(tk, text=\"Click to Restart Game\", \n command=self.restart)\n self.restart_button.pack()
\nThe command
associated with the button is the function on our Game class called restart
- this is the bit of code that takes care of hiding the \"Game Over\" text, putting the ball and paddle back in their starting positions, and so on.
Hope that helps somewhat.
", "date_published": "2014-08-29T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/08/28/co-existence.html", "title": "Co-existence", "url": "https://jasonrbriggs.com/journal/2014/08/28/co-existence.html", "content_text": "Marta C writes:\n\n> _I'm new in programming. I just want to know if it would be too hard or complicated to use Python 2.7_\n> _with the Python for Kids book? I am still practicing for a class I took with v 2.7. Can I have both_\n> _IDLE 2.7 and 3 in the system and use them separately and not run into problems?_\n> _Thank you._\n\nMost of the examples in the book will work with Python 2.7 -- but some won't without modification (particularly anything using the\ntkinter module). And you may hit subtle problems which will be harder to figure out as a consequence.\nHowever, you can install both Python 2.7 and 3 on the same system (you didn't say, but I'm guessing you're using Windows -- after installation, you'll find you've got both c:\\Python27 and c:\\Python34 directories, assuming you install the latest Python version, on your hard drive) -- just make sure you select the correct directory when setting up the IDLE shortcut (described in Chapter 1).", "content_html": "Marta C writes:
\n\n\nI'm new in programming. I just want to know if it would be too hard or complicated to use Python 2.7\nwith the Python for Kids book? I am still practicing for a class I took with v 2.7. Can I have both\nIDLE 2.7 and 3 in the system and use them separately and not run into problems?\nThank you.
\n
Most of the examples in the book will work with Python 2.7 -- but some won't without modification (particularly anything using the\ntkinter module). And you may hit subtle problems which will be harder to figure out as a consequence.\nHowever, you can install both Python 2.7 and 3 on the same system (you didn't say, but I'm guessing you're using Windows -- after installation, you'll find you've got both c:\\Python27 and c:\\Python34 directories, assuming you install the latest Python version, on your hard drive) -- just make sure you select the correct directory when setting up the IDLE shortcut (described in Chapter 1).
", "date_published": "2014-08-28T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/08/17/is-the-animation-loop-necessary.html", "title": "Is The Animation Loop Necessary?", "url": "https://jasonrbriggs.com/journal/2014/08/17/is-the-animation-loop-necessary.html", "content_text": "Christopher D writes:\n\n> _I'm currently working through your book and enjoying it immensely._\n> _The following is baffling me though, so hoping you can help._\n>\n> _In Chapter 13, page 197 (after creating the ball object), you wrote:_\n> _\"If you run this program now using Run>Module, the canvas will appear for_\n> _a split second and then vanish\". You then go on to write about how its necessary_\n> _to add the animation loop to stop this happening._\n>\n> _My window appears and draws the ball correctly, but does not vanish. Reading through_\n> _the code I don't understand why it's expected to disappear either. This seems to be a_\n> _key point so would be grateful if you could shed light! I'm running_\n> _Python 3.4.1 by the way._\n>\n> _Thank you in advance for your help!_\n\nYou've found an error in the book, I'm afraid. If you run the code using the Python console (try it by opening a command prompt, or terminal, and running `python bounce.py`), the window will indeed appear and vanish. The basic idea is, there's nothing left for it to do, so no reason for the window to remain open. That's the reason for adding an animation loop of some kind (in the book I use a very basic while-loop, but tkinter also has a `mainloop` function for doing this).\nHowever, when you run the same code with Idle (the Python Shell), which is written using [tkinter](https://docs.python.org/3.4/library/tkinter.html), the window remains open because there's already a main loop running (started by the Shell itself). So the book is both right and wrong, I guess, depending on how you want to run the code.\nThe [errata](https://jasonrbriggs.com/python-for-kids/errata.html) has been updated accordingly. Thanks for the \"bug report\".", "content_html": "Christopher D writes:
\n\n\nI'm currently working through your book and enjoying it immensely.\nThe following is baffling me though, so hoping you can help.
\nIn Chapter 13, page 197 (after creating the ball object), you wrote:\n\"If you run this program now using Run>Module, the canvas will appear for\na split second and then vanish\". You then go on to write about how its necessary\nto add the animation loop to stop this happening.
\nMy window appears and draws the ball correctly, but does not vanish. Reading through\nthe code I don't understand why it's expected to disappear either. This seems to be a\nkey point so would be grateful if you could shed light! I'm running\nPython 3.4.1 by the way.
\nThank you in advance for your help!
\n
You've found an error in the book, I'm afraid. If you run the code using the Python console (try it by opening a command prompt, or terminal, and running python bounce.py
), the window will indeed appear and vanish. The basic idea is, there's nothing left for it to do, so no reason for the window to remain open. That's the reason for adding an animation loop of some kind (in the book I use a very basic while-loop, but tkinter also has a mainloop
function for doing this).\nHowever, when you run the same code with Idle (the Python Shell), which is written using tkinter, the window remains open because there's already a main loop running (started by the Shell itself). So the book is both right and wrong, I guess, depending on how you want to run the code.\nThe errata has been updated accordingly. Thanks for the \"bug report\".
Jean-Jacques B writes:
\n\n\nI am trying to set up my iMac for the book, having trouble with the automator script:
\nopen -a \"Applications/Python 3.2/IDLE.app\" --args -n
\nRun Shell Script failed\nopen: unrecognized option '--args'
\nI can get python to launch the other ways, but then turtle doesn't work.
\n
This had me stumped for a moment (couldn't find any similar errors when I googled).
\nIt actually looks like a poorly handled error in the Automator. If you copy+paste what you entered into the Terminal, you get an entirely different error message:
\n$ open -a \"Applications/Python 3.2/IDLE.app\" --args -n\nUnable to find application named 'Applications/Python 3.2/IDLE.app'
\nWhich hopefully helps you figure out where you went wrong... try adding a / (slash) in front of the path to IDLE. eg.:
\nopen -a \"/Applications/Python 3.2/IDLE.app\" --args -n
",
"date_published": "2014-07-27T23:52:53+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2014/06/15/python-3.4-shell.html",
"title": "Python 3.4 Shell",
"url": "https://jasonrbriggs.com/journal/2014/06/15/python-3.4-shell.html",
"content_text": "Kirk K writes:\n\n> _On page 12 it says File>New Window but I cannot find it on our Windows version 3.4.1. Please advise._\n\nIt looks like, as of Python 3.4, they've changed the menu, so File->New Window has become File->New File (which makes the Shell consistent with other text editors, at least). It still has the same behaviour though - opening a new window for typing in your Python code.",
"content_html": "Kirk K writes:
\n\n\nOn page 12 it says File>New Window but I cannot find it on our Windows version 3.4.1. Please advise.
\n
It looks like, as of Python 3.4, they've changed the menu, so File->New Window has become File->New File (which makes the Shell consistent with other text editors, at least). It still has the same behaviour though - opening a new window for typing in your Python code.
", "date_published": "2014-06-15T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/06/13/restart-when-running-tkinter.html", "title": "Restart when running tkinter", "url": "https://jasonrbriggs.com/journal/2014/06/13/restart-when-running-tkinter.html", "content_text": "Craig S writes:\n\n> _My son is having a problem running the random rectangle program on page 174 of Python for Kids. He is using version 2.7.7,_\n> _so the Tkinter module must be capitalized (just so you don't suggest to capitalize it). Every time he tries to run the_\n> _module, it comes up with a new window saying, \"RESTART\". He tried to copy and paste your code, but came up with the_\n> _same results. This is the code he's written._\n> _from Tkinter import *_\n> _import random_\n> _tk = Tk()_\n> _canvas = Canvas(tk, width=400,height=400)_\n> _def random\\_rectangle(width, height):_\n> ...\n> _random\\_rectangle(400, 400)_\n>\n> _This is what comes up when he runs it._\n> _Python 2.7.7 (default, Jun 1 2014, 14:17:13) on win32_\n> _Type \"copyright\", \"credits\" or \"license()\" for more information._\n> _>>> =============== RESTART ===============_\n>\n> _Please share some advice. Thanks._\n\nA couple of thoughts:\n\n1. He's missing the `pack` function after the 4th line of that code (`canvas.pack()`)\n2. You're probably not running Idle in \"No Subprocess\" mode (see Chapter 1 of the book for setup instructions). If that doesn't work for you, for some reason, then best thing to do is use a text editor, save the code and then run it from the command prompt by typing `python yourscript.py` (see [http://windows.microsoft.com/en-us/windows/command-prompt-faq](http://windows.microsoft.com/en-us/windows/command-prompt-faq) for instructions on running the command prompt if you're not aware how to do that)\n3. You may hit other weird issues if you're not using Python3, since all the code in the book was written and tested with 3.x. Much of it is probably fine, but no guarantees there...", "content_html": "Craig S writes:
\n\n\nMy son is having a problem running the random rectangle program on page 174 of Python for Kids. He is using version 2.7.7,\nso the Tkinter module must be capitalized (just so you don't suggest to capitalize it). Every time he tries to run the\nmodule, it comes up with a new window saying, \"RESTART\". He tried to copy and paste your code, but came up with the\nsame results. This is the code he's written.\nfrom Tkinter import *\nimport random\ntk = Tk()\ncanvas = Canvas(tk, width=400,height=400)\ndef random_rectangle(width, height):\n ...\nrandom_rectangle(400, 400)
\nThis is what comes up when he runs it.\nPython 2.7.7 (default, Jun 1 2014, 14:17:13) on win32\nType \"copyright\", \"credits\" or \"license()\" for more information.\n>>> =============== RESTART ===============
\nPlease share some advice. Thanks.
\n
A couple of thoughts:
\npack
function after the 4th line of that code (canvas.pack()
)python yourscript.py
(see http://windows.microsoft.com/en-us/windows/command-prompt-faq for instructions on running the command prompt if you're not aware how to do that)Koki Y writes:
\n\n\nI have a question. You use % for format instead .format().\nIn the python tutorial, it is written that % format is an older version of format.\nWhat's the point of using % format?
\n
The book uses the % operator (also known as the interpolation operator) basically through omission more than anything else.\nThe first electronic version was written for Python2 (back in 2006/2007), then updated to be compatible with both 2 and 3. While it was almost totally rewritten, to be published as \"Python for Kids\", some of the existing text was repurposed -- however, the string formatting section wasn't specifically updated for Python 3. I suspect that's somehing we should probably fix when/if it's reprinted again.
\nBy all means, use the format
function as detailed in the Python documentation.
Marcin S writes:
\n\n\nI am currently testing your book on my girlfriend who is not a kid anymore but a person that has not\nwritten any code in her entire life. To assist her better I have read the whole book.\nI think I spent my money well when I bought it.
\nStill, I have some questions and remarks.
\nDid you consider to emphasize more we are using Python 3 in the entire book? I know that the reader\nis instructed to download that version, but if someone uses Python 2 for some reason (e.g.\ncomputer science classroom with outdated software), one will get different results. In\nthe context of your book I have found two important cases:\n1) division always produces a float in Python3 because we no longer have a strict difference between\nintegers and floats,\n2) input() works like raw_input() from Python2, while input() in Python2 made implicit eval(). [1]
\nThe errata mentions input() behaves differently than readline() depending on the context -- console\nor shell. I am unable to replicate it. BTW, the parameter to read()/readline() specifies the maximum\nnumber of characters to read, not the exact number. And there is one more thing -- if one reads less\ncharacters than available on stdin, remaining characters will be read on the next call to read()/readline(). [2]
\nAre strings enclosed in triple double-quotes omitted as reserved for documentation? I think only triple\nsingle-quotes are mentioned in the book. [3]
\nWhy did you choose to name classes with plural names (class Giraffes) instead of singular (class Giraffe)? [4]
\nThe \"is\" keyword is mentioned in the keywords section as a complicated concept and is omitted in the\nexamples. I have one remark on that: PEP8 suggests using \"is\" when checking if something is None\n(not with \"==\"). [5]
\nI have seen range() with 3 arguments mentioned later in the book. Did you consider mentioning\nslices ([a:b:c]) as well? [6]
\nDid you consider mentioning \"for\" and \"while\" with the optional \"else\" block? [6]
\nThe book mentions random.choice() but the bounce game uses shuffle() and picking by index instead. [7]
\nMr. Stick Man checks for collisions using comparisons glued with \"and\". Did you consider constructs\nlike \"x1 < x < x2\" instead of \"x1 < x and x < x2\"? [8]
\nWhy did you choose a Tk construct based on sequence: update_idletasks(), update(), sleep()\ninstead of mainloop() with rescheduling with Tk.after()? There would not be any active wait then\nand it would be event-driven. Is not the update_idletasks() included in update()? [9]
\n
I've annotated your comments so I can address each in turn, but the answer to many of your points is somewhat similar:
\n[1] No, at the time of writing, I didn't consider more emphasis was needed, other than what is detailed in the first chapter. But as time has gone on, the differences between 2 and 3 account for a significantly large percentage of the questions I get about the book, so perhaps something additional makes sense.\n[2] The problem is reproducible in Python3.2 (and older versions). In 3.3 onwards, the max characters parameter works as expected.\n[3] No, the triple double-quotes were omitted essentially for simplification reasons. To make it less confusing for younger readers.\n[4] I chose plural class names mainly to try to indicate class as a kind of grouping - trying to distinguish between that and singular object instances. Yes, not particularly standard, but I had a (possibly vain) hope it would help to highlight the difference between class and object.\n[5] \"is\" was omitted again for simplification reasons -- to avoid a complicated description of how object identity works.\n[6] Again, slices and else
blocks in for
/while
loops were omitted for simplification.\n[7] You'll find a description of the shuffle
function on page 136.\n[8] Another one omitted to simplify things. Combining conditions with and
and or
is, I believe, more straightforward for kids to understand (even if x < y < z is a bit cleaner)\n[9] This one came up in the review from one of the technical proof readers. mainloop
is definitely the better (read as correct) approach, but I wanted to stick with a loop and update/update_idletasks
because it made it obvious, to the reader, what is happening. Each loop tells one of the objects to do something (move and draw), and then triggers Tk to redraw the screen (the reason for using both update
and update_idletasks
is that when writing the book -- with an earlier version of Python3 -- I saw some animation jittering when using only the one call. Using both seemed to resolve that issue. Perhaps I should've checked why at the time, and maybe it's no longer an problem with Python3.4)
Hope that helps clarify some of your questions...
", "date_published": "2014-05-19T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/05/18/intermediate-python-resources.html", "title": "Intermediate Python Resources", "url": "https://jasonrbriggs.com/journal/2014/05/18/intermediate-python-resources.html", "content_text": "Jim G writes:\n\n> _I'm currently going through your book python for kids. I was wondering what books or other sources you_\n> _recommend for learning more about python_\n\nWell, there are a heap of online tutorials, and dead-tree, printed books to choose from. However, I have an alternate suggestion to further reading.\n\nOnce you've learned the basics, why not pick a project? Find something you want to create - whether that's a game, a desktop application, a website or something else - make sure you have the [Python documentation bookmarked](https://docs.python.org/3/), and a search engine to hand, and start working on it. You can't beat actually coding for improving your knowledge and ability.\n\nLet's say you decide to write a program to send a message from one computer to another, on your home network. That might lead you to the [socket module](https://docs.python.org/3/library/socket.html#module-socket) in the Python [modules](https://docs.python.org/3/py-modindex.html) documentation. Assuming you find that too opaque, you might search for a [\"python networking tutorial\"](https://duckduckgo.com/?q=python+networking+tutorial) or perhaps a [\"simple python socket example\"](https://duckduckgo.com/?q=simple+python+socket+example) - but either way, the investigation, and putting that information to work in a program of your own will be a much more valuable learning experience than just reading a dry chapter about networking in some resource.\n\n", "content_html": "Jim G writes:
\n\n\nI'm currently going through your book python for kids. I was wondering what books or other sources you\nrecommend for learning more about python
\n
Well, there are a heap of online tutorials, and dead-tree, printed books to choose from. However, I have an alternate suggestion to further reading.
\nOnce you've learned the basics, why not pick a project? Find something you want to create - whether that's a game, a desktop application, a website or something else - make sure you have the Python documentation bookmarked, and a search engine to hand, and start working on it. You can't beat actually coding for improving your knowledge and ability.
\nLet's say you decide to write a program to send a message from one computer to another, on your home network. That might lead you to the socket module in the Python modules documentation. Assuming you find that too opaque, you might search for a \"python networking tutorial\" or perhaps a \"simple python socket example\" - but either way, the investigation, and putting that information to work in a program of your own will be a much more valuable learning experience than just reading a dry chapter about networking in some resource.
", "date_published": "2014-05-18T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/03/10/python-on-the-ipad.html", "title": "Python on the iPad?", "url": "https://jasonrbriggs.com/journal/2014/03/10/python-on-the-ipad.html", "content_text": "Beth S writes:\n\n> _I teach gifted elementary-aged students in Albuquerque, NM. A few of my students and I have been working through your book._\n> _We have limited desktops in our classroom, but we also have access to several iPads. In researching the various apps_\n> _available, I’ve realized that most (if not all?) do not include the _tkinter module. To be honest, I’m rather new to_\n> _programming myself!_\n>\n> _Do you have a recommendation for an iPad app that would be appropriate for students using your book?_\n>\n> _Thank you for your time and your ability to clearly explain the basics of Python!_\n\nI'm afraid I don't know of any way to use an iPad for Python, other than by jail-breaking the device (and even then I have no idea whether tkinter would work anyway - I think unlikely).\n\nThe only thought I had was whether you could use the desktop PCs in your class to run multiple VMs (using something like [VirtualBox](https://www.virtualbox.org)) and then connect to those using a [Remote Desktop App](http://appadvice.com/appguides/show/remote-desktop-apps) for the iPad. Not straightforward to set up, but it might accomplish what you want (assuming the desktops are reasonably powerful of course).\n\nSorry I can't be much help there.\n\n_Update: since sending my initial reply, I came across [this discussion](http://permalink.gmane.org/gmane.comp.python.tkinter/3332), which explains why you're not likely to see tkinter on the iPad anytime soon._", "content_html": "Beth S writes:
\n\n\nI teach gifted elementary-aged students in Albuquerque, NM. A few of my students and I have been working through your book.\nWe have limited desktops in our classroom, but we also have access to several iPads. In researching the various apps\navailable, I’ve realized that most (if not all?) do not include the _tkinter module. To be honest, I’m rather new to\nprogramming myself!
\nDo you have a recommendation for an iPad app that would be appropriate for students using your book?
\nThank you for your time and your ability to clearly explain the basics of Python!
\n
I'm afraid I don't know of any way to use an iPad for Python, other than by jail-breaking the device (and even then I have no idea whether tkinter would work anyway - I think unlikely).
\nThe only thought I had was whether you could use the desktop PCs in your class to run multiple VMs (using something like VirtualBox) and then connect to those using a Remote Desktop App for the iPad. Not straightforward to set up, but it might accomplish what you want (assuming the desktops are reasonably powerful of course).
\nSorry I can't be much help there.
\nUpdate: since sending my initial reply, I came across this discussion, which explains why you're not likely to see tkinter on the iPad anytime soon.
", "date_published": "2014-03-10T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2014/02/08/but-it-doesn't-mean-anything.html", "title": "\"But it doesn't mean anything\"", "url": "https://jasonrbriggs.com/journal/2014/02/08/but-it-doesn't-mean-anything.html", "content_text": "Jeremy Paxman [talking with a conservative activist](http://politicalscrapbook.net/2014/02/tory-boss-of-government-coding-education-initiative-cant-code-lottie-dexter/) on the \"Year of Code\" (at about 9 minutes in) announces: \"But it doesn't mean anything\".\n\n\n\nBy the same token you could quite comfortably argue that Hanzi, or Kanji, (or Arabic, Thai, Hindi or any of the other non-Latin derived scripts) don't mean anything. But a good percentage of the world's population seem to get by quite well using them...\n\n_(Oh yeah... and the artistic looking garbage on your big screen really doesn't mean anything ツ)_", "content_html": "Jeremy Paxman talking with a conservative activist on the \"Year of Code\" (at about 9 minutes in) announces: \"But it doesn't mean anything\".
\n\n\nBy the same token you could quite comfortably argue that Hanzi, or Kanji, (or Arabic, Thai, Hindi or any of the other non-Latin derived scripts) don't mean anything. But a good percentage of the world's population seem to get by quite well using them...
\n(Oh yeah... and the artistic looking garbage on your big screen really doesn't mean anything ツ)
", "date_published": "2014-02-08T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/12/31/tcl-tk-warning-message-when-starting-idle.html", "title": "Tcl/Tk warning message when starting IDLE", "url": "https://jasonrbriggs.com/journal/2013/12/31/tcl-tk-warning-message-when-starting-idle.html", "content_text": "Stan W writes (NB. edited for brevity):\n\n> _Over the last couple of days I have started using your great book with my two sons (13 and 15 years old)._\n> _I'm reaching out to you with the following question because I have noticed other people asking about the same issue online, with_\n> _at least one mentioning your book, so I think you posting the question and answer to your blog might help other people in addition_\n> _to me and my sons._\n>\n> _We are using Mac OSX and have installed Python 3.3.3 from python.org, and are getting this message when opening IDLE:_\n>\n> _\"WARNING: The version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk/ for_\n> _current information.\"_\n>\n> _I have installed \"Mac OS X 64-bit/32-bit Installer (3.3.3) for Mac OS X 10.6 and later\" (file: python-3.3.3-macosx10.6.dmg) and_\n> _installed the \"ActiveTcl 8.6.1 for Mac OS X (10.5+, x86_64/x86)\" (file: ActiveTcl8.6.1.1.297588-macosx10.5-i386-x86_64-threaded),_\n> _but IDLE keeps showing the same error message._\n>\n> _Thank you very much for any help you can provide!_\n\nI'm not convinced ActiveTcl 8.6.1 is the right version to install - I suspect rather than installing the latest and greatest, you should be using version 8.5.15.0. Python (and thus IDLE) will probably be using the latest **8.5** version of Tcl/Tk (i.e. 8.5.**x**) — you're installing a completely different version (8.6), which it's not looking for at all. Hence even though you think you've re-installed, you'll still be getting the same error message.\n\nHope that helps.\n\n", "content_html": "Stan W writes (NB. edited for brevity):
\n\n\nOver the last couple of days I have started using your great book with my two sons (13 and 15 years old).\nI'm reaching out to you with the following question because I have noticed other people asking about the same issue online, with\nat least one mentioning your book, so I think you posting the question and answer to your blog might help other people in addition\nto me and my sons.
\nWe are using Mac OSX and have installed Python 3.3.3 from python.org, and are getting this message when opening IDLE:
\n\"WARNING: The version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk/ for\ncurrent information.\"
\nI have installed \"Mac OS X 64-bit/32-bit Installer (3.3.3) for Mac OS X 10.6 and later\" (file: python-3.3.3-macosx10.6.dmg) and\ninstalled the \"ActiveTcl 8.6.1 for Mac OS X (10.5+, x86_64/x86)\" (file: ActiveTcl8.6.1.1.297588-macosx10.5-i386-x86_64-threaded),\nbut IDLE keeps showing the same error message.
\nThank you very much for any help you can provide!
\n
I'm not convinced ActiveTcl 8.6.1 is the right version to install - I suspect rather than installing the latest and greatest, you should be using version 8.5.15.0. Python (and thus IDLE) will probably be using the latest 8.5 version of Tcl/Tk (i.e. 8.5.x) — you're installing a completely different version (8.6), which it's not looking for at all. Hence even though you think you've re-installed, you'll still be getting the same error message.
\nHope that helps.
", "date_published": "2013-12-31T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/12/14/left-and-right,-or-top-and-bottom.html", "title": "Left and right, or top and bottom", "url": "https://jasonrbriggs.com/journal/2013/12/14/left-and-right,-or-top-and-bottom.html", "content_text": "Matthias writes:\n\n> _My name is Matthias and I am 7 years old and I like Python. I knew a little about Python before I read your book, but I am_\n> _learning more by reading your book. I like your book._\n>\n> _I think on page 202 is a little mistake._\n> _You wrote:_\n>\n> _\"We'll use this new object variable in the draw function to see if the ball has hit the top or bottom of the canvas:\"_\n>\n> _Shouldn't it be \"left or right sides of the canvas\" instead?_\n\nHi Matthias. You're doing well to have gotten as far as you have, at 7 years of age. Well done!\n\nYou're absolutely right about the mistake, and I've updated the [errata](https://jasonrbriggs.com/python-for-kids/errata.html) accordingly. Thanks very much for the \"bug report\". ツ\n", "content_html": "Matthias writes:
\n\n\nMy name is Matthias and I am 7 years old and I like Python. I knew a little about Python before I read your book, but I am\nlearning more by reading your book. I like your book.
\nI think on page 202 is a little mistake.\nYou wrote:
\n\"We'll use this new object variable in the draw function to see if the ball has hit the top or bottom of the canvas:\"
\nShouldn't it be \"left or right sides of the canvas\" instead?
\n
Hi Matthias. You're doing well to have gotten as far as you have, at 7 years of age. Well done!
\nYou're absolutely right about the mistake, and I've updated the errata accordingly. Thanks very much for the \"bug report\". ツ
", "date_published": "2013-12-14T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/10/30/problem-with-the-turtle-module.html", "title": "Problem with the turtle module", "url": "https://jasonrbriggs.com/journal/2013/10/30/problem-with-the-turtle-module.html", "content_text": "Mark F writes:\n\n> _I think that it's a great book but I am running into one issue. If you're not too busy, I'm hoping you could answer it for me._\n> _In Chapter 8, Classes and Objects, you reintroduce the turtle module. You say that we can create 'an object of the pen class,'_\n> _which makes sense._\n>\n> _import turtle_ \n> _avery = turtle.pen()_ \n> _kate = turtle.pen()_ \n>\n> _However, when I attempt to move the turtle using either one of those objects, I get this error:_\n>\n> _avery.forward(50)_ \n> _Traceback (most recent call last):_ \n> _ File \"\\Mark F writes:
\n\n\nI think that it's a great book but I am running into one issue. If you're not too busy, I'm hoping you could answer it for me.\nIn Chapter 8, Classes and Objects, you reintroduce the turtle module. You say that we can create 'an object of the pen class,'\nwhich makes sense.
\nimport turtle
\n
\navery = turtle.pen()
\nkate = turtle.pen()However, when I attempt to move the turtle using either one of those objects, I get this error:
\navery.forward(50)
\n
\nTraceback (most recent call last):
\n File \"\\<pyshell#3>\", line 1, in
\n avery.forward(50)
\nAttributeError: 'dict' object has no attribute 'forward'In fact, the only time I can get the turtle to move is if i simply type in turtle.forward(). I am using version 3.3\nbut have tried with 3.2 and encounter the same error. Please let me know why I keep getting this error so\nthat I can keep moving forward.
\n
If you compare your code snippet above, with the example in the book, there's one fairly obvious difference: lowercase \"p\" versus uppercase \"P\". The question is, why is it such a problem?\nIn the turtle module, Pen
and pen
are two distinct things. We can see the difference if we run the Python console (or Shell), and try out the following code:
>>> import turtle\n>>> turtle.pen\n<function pen at 0x10117fe60>\n>>> turtle.Pen\n<class turtle.Turtle>
\nWithout the brackets (i.e. without entering pen()
or Pen()
), Python just prints out a simple description, so we can see that pen
is a function, and Pen
is a class (good rule of thumb: names which start with an uppercase letter are generally classes, names with a lowercase letter are functions, variables, and so on). For the example code, we want to create a Pen
object (we don't want to call the pen
function) - so if you change your code to...
import turtle\navery = turtle.Pen()\nkate = turtle.Pen()
\n...you should have a bit more success.
", "date_published": "2013-10-30T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/09/26/loop-confusion.html", "title": "Loop confusion", "url": "https://jasonrbriggs.com/journal/2013/09/26/loop-confusion.html", "content_text": "Justin B writes:\n\n> _I recently started the section on \"For Loops\" and am somewhat confused about something._\n> _The section (page 55) runs a loop for \"HugeHairyPants.\" I setup the loop as you indicated and actually_\n> _understood the result just fine._\n>\n> _However, I decided to add a variable in the mix and went one step further. Here is my script:_\n>\n> _hugehairypants = ['huge', 'hairy', 'pants']_\n> _for i in hugehairypants:_\n> _print(i)_\n> _for j in hugehairypants:_\n> _print(j)_\n> _for k in hugehairypants:_\n> _print(k)_\n>\n> _This loop doesn't seem to follow the same progression of the other loop or maybe I just don't_\n> _understand it correctly. I figured it would print a variable from i and then j and then print_\n> _the full loop of items in k, but it doesn't seem to do that. If you have a moment, could explain_\n> _how this loop would work?_\n\nIf we look at your code and mark each loop, then mark the output as well, and indent each line in terms of the loop it matches, hopefully it might help you see what's happening:\n\n```python\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n print(i)\n for j in hugehairypants: # LOOP 2\n print(j)\n for k in hugehairypants: # LOOP 3\n print(k)\n```\n\nAnd the output:\n\n```\nhuge (LOOP 1, first time)\n huge (LOOP 2, first time)\n huge (LOOP 3, first time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, first time)\n huge (LOOP 3, second time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, first time)\n huge (LOOP 3, third time)\n hairy (LOOP 3)\n pants (LOOP 3)\nhairy (LOOP 1, first time)\n huge (LOOP 2, second time)\n huge (LOOP 3, fourth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, second time)\n huge (LOOP 3, fifth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, second time)\n huge (LOOP 3, sixth time)\n hairy (LOOP 3)\n pants (LOOP 3)\npants (LOOP 1, first time)\n huge (LOOP 2, third time)\n huge (LOOP 3, seventh time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, third time)\n huge (LOOP 3, eighth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, third time)\n huge (LOOP 3, ninth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n```\n\nSo loop 1 outputs the list once, loop 2 outputs the list three times, and loop 3 outputs the list nine times in total.\n\nAs a side note, we could have also altered the code to do the indentation for us:\n\n```python\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n print(i)\n for j in hugehairypants: # LOOP 2\n print(' %s' % j)\n for k in hugehairypants: # LOOP 3\n print(' %s' % k)\n```\n\nAnd, while sometimes it's a good idea to work things out by hand (as I did in the example output above), just so you can be sure you understand the process, we could even use counters to print out the number of times we've hit each loop, rather than figuring it out manually:\n\n```python\ntime_label = ['','first','second','third','fourth','fifth','sixth','seventh','eighth','ninth']\ni_counter = 0\nj_counter = 0\nk_counter = 0\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n if i == 'huge':\n i_counter += 1\n print('%s (LOOP 1, %s time)' % (i, time_label[i_counter]))\n for j in hugehairypants: # LOOP 2\n if j == 'huge':\n j_counter += 1\n print(' %s (LOOP 2, %s time)' % (j, time_label[j_counter]))\n for k in hugehairypants: # LOOP 3\n if k == 'huge':\n k_counter += 1\n print(' %s (LOOP 3, %s time)' % (k, time_label[k_counter]))\n```", "content_html": "Justin B writes:
\n\n\nI recently started the section on \"For Loops\" and am somewhat confused about something.\nThe section (page 55) runs a loop for \"HugeHairyPants.\" I setup the loop as you indicated and actually\nunderstood the result just fine.
\nHowever, I decided to add a variable in the mix and went one step further. Here is my script:
\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants:\n print(i)\n for j in hugehairypants:\n print(j)\n for k in hugehairypants:\n print(k)
\nThis loop doesn't seem to follow the same progression of the other loop or maybe I just don't\nunderstand it correctly. I figured it would print a variable from i and then j and then print\nthe full loop of items in k, but it doesn't seem to do that. If you have a moment, could explain\nhow this loop would work?
\n
If we look at your code and mark each loop, then mark the output as well, and indent each line in terms of the loop it matches, hopefully it might help you see what's happening:
\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n print(i)\n for j in hugehairypants: # LOOP 2\n print(j)\n for k in hugehairypants: # LOOP 3\n print(k)
\nAnd the output:
\nhuge (LOOP 1, first time)\n huge (LOOP 2, first time)\n huge (LOOP 3, first time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, first time)\n huge (LOOP 3, second time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, first time)\n huge (LOOP 3, third time)\n hairy (LOOP 3)\n pants (LOOP 3)\nhairy (LOOP 1, first time)\n huge (LOOP 2, second time)\n huge (LOOP 3, fourth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, second time)\n huge (LOOP 3, fifth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, second time)\n huge (LOOP 3, sixth time)\n hairy (LOOP 3)\n pants (LOOP 3)\npants (LOOP 1, first time)\n huge (LOOP 2, third time)\n huge (LOOP 3, seventh time)\n hairy (LOOP 3)\n pants (LOOP 3)\n hairy (LOOP 2, third time)\n huge (LOOP 3, eighth time)\n hairy (LOOP 3)\n pants (LOOP 3)\n pants (LOOP 2, third time)\n huge (LOOP 3, ninth time)\n hairy (LOOP 3)\n pants (LOOP 3)
\nSo loop 1 outputs the list once, loop 2 outputs the list three times, and loop 3 outputs the list nine times in total.
\nAs a side note, we could have also altered the code to do the indentation for us:
\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n print(i)\n for j in hugehairypants: # LOOP 2\n print(' %s' % j)\n for k in hugehairypants: # LOOP 3\n print(' %s' % k)
\nAnd, while sometimes it's a good idea to work things out by hand (as I did in the example output above), just so you can be sure you understand the process, we could even use counters to print out the number of times we've hit each loop, rather than figuring it out manually:
\ntime_label = ['','first','second','third','fourth','fifth','sixth','seventh','eighth','ninth']\ni_counter = 0\nj_counter = 0\nk_counter = 0\nhugehairypants = ['huge', 'hairy', 'pants']\nfor i in hugehairypants: # LOOP 1\n if i == 'huge':\n i_counter += 1\n print('%s (LOOP 1, %s time)' % (i, time_label[i_counter]))\n for j in hugehairypants: # LOOP 2\n if j == 'huge':\n j_counter += 1\n print(' %s (LOOP 2, %s time)' % (j, time_label[j_counter]))\n for k in hugehairypants: # LOOP 3\n if k == 'huge':\n k_counter += 1\n print(' %s (LOOP 3, %s time)' % (k, time_label[k_counter]))
",
"date_published": "2013-09-26T23:52:53+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2013/09/19/python-installation-confusion-on-mac-os-x.html",
"title": "Python installation confusion on Mac OS X",
"url": "https://jasonrbriggs.com/journal/2013/09/19/python-installation-confusion-on-mac-os-x.html",
"content_text": "Justin J writes:\n\n> _I installed python 3.3.2 for my macbook running version 10.6.8 and typed this in,_\n> _**open -a \"/Applications/Python 3.2/IDLE.app\" --args -n** and it didn't work:_\n>\n> _\"The action `Run Shell Script` encountered an error. Check the action's properties and try running the workflow again\"_\n>\n> _I installed both versions 32 bit and 64/32 bit and it still didn't work._\n>\n> _I'm assuming because I installed 3.3.2, I had to change it to **open -a \"/Applications/Python 3.3/IDLE.app\" --args -n**._\n> _In other words change Python 3.2 to Python 3.3. Then it worked! Unfortunately I think it was running on the 64/32 version_\n> _which python mentioned something about ActiveTcl 8.5. It recommended I download 32, so I got rid of 64/32 and_\n> _re-downloaded 32 bit and it finally gave me no error in the shell._\n>\n> _I thought I'd ask if this was an ok thing for me to do?_\n\nAs per the instructions on [this page](http://www.python.org/download/mac/tcltk/), you'll need to install ActiveTcl in order for IDLE and Tkinter to work properly (both are used heavily in the book) with Mac OS X 10.6.\n\n[ActiveState](http://www.activestate.com/activetcl/downloads) have a dmg installation file, so once you've downloaded it, double-click on the file, and a dialog will appear:\n\n[![ActiveTcl installation dialog](https://jasonrbriggs.com/journal/2013/09/19/activetcl-dialog-small.png)](/journal/2013/09/19/activetcl-dialog.png)\n\nYou may need to control-click on the ActiveTcl package, if you double-click and get the error message _\"ActiveTcl-8.5.pkg can't be opened because it is from an unidentified developer\"._ So if that error message appears, hold down the Control key, click on the icon and select Open from the menu displayed, then click Open on the following screen. Click through the next few screens (you'll be asked to agree to the license and so on), and on the final screen, once you click Install, you'll get promoted for an administrator username & password.\n\nApart from that, your change to the open command is correct, so once ActiveTcl is installed, you should be good to go.\n\n",
"content_html": "Justin J writes:
\n\n\nI installed python 3.3.2 for my macbook running version 10.6.8 and typed this in,\nopen -a \"/Applications/Python 3.2/IDLE.app\" --args -n and it didn't work:
\n\"The action
\nRun Shell Script
encountered an error. Check the action's properties and try running the workflow again\"I installed both versions 32 bit and 64/32 bit and it still didn't work.
\nI'm assuming because I installed 3.3.2, I had to change it to open -a \"/Applications/Python 3.3/IDLE.app\" --args -n.\nIn other words change Python 3.2 to Python 3.3. Then it worked! Unfortunately I think it was running on the 64/32 version\nwhich python mentioned something about ActiveTcl 8.5. It recommended I download 32, so I got rid of 64/32 and\nre-downloaded 32 bit and it finally gave me no error in the shell.
\nI thought I'd ask if this was an ok thing for me to do?
\n
As per the instructions on this page, you'll need to install ActiveTcl in order for IDLE and Tkinter to work properly (both are used heavily in the book) with Mac OS X 10.6.
\nActiveState have a dmg installation file, so once you've downloaded it, double-click on the file, and a dialog will appear:
\n\nYou may need to control-click on the ActiveTcl package, if you double-click and get the error message \"ActiveTcl-8.5.pkg can't be opened because it is from an unidentified developer\". So if that error message appears, hold down the Control key, click on the icon and select Open from the menu displayed, then click Open on the following screen. Click through the next few screens (you'll be asked to agree to the license and so on), and on the final screen, once you click Install, you'll get promoted for an administrator username & password.
\nApart from that, your change to the open command is correct, so once ActiveTcl is installed, you should be good to go.
", "date_published": "2013-09-19T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/08/27/what-is--n-for.html", "title": "What is -n for", "url": "https://jasonrbriggs.com/journal/2013/08/27/what-is--n-for.html", "content_text": "John writes:\n\n> _Quick question regarding the -n used in the shortcut for IDLE. I realize that it starts IDLE with no subprocesses,_\n> _but what does that mean and why do we want to do it?_\n\nThere's precious little on the net describing what the -n switch does. From the IDLE documentation:\n\n> If IDLE is started with the -n command line switch it will run in a\n> single process and will not create the subprocess which runs the RPC\n> Python execution server. This can be useful if Python cannot create\n> the subprocess or the RPC socket interface on your platform. However,\n> in this mode user code is not isolated from IDLE itself. Also, the\n> environment is not restarted when Run/Run Module (F5) is selected. If\n> your code has been modified, you must reload() the affected modules and\n> re-import any specific items (e.g. from foo import baz) if the changes\n> are to take effect. For these reasons, it is preferable to run IDLE\n> with the default subprocess if at all possible.\n\nWhich, I admit, doesn't help a huge amount...\n\nFor the purposes of [Python for Kids](https://jasonrbriggs.com/python-for-kids) however, all you really need to know is that certain graphical libraries (such as turtle and, I seem to recall, tkinter) will exhibit weird behaviour (such as locking up/hanging) if you don't run IDLE using the -n switch.", "content_html": "John writes:
\n\n\nQuick question regarding the -n used in the shortcut for IDLE. I realize that it starts IDLE with no subprocesses,\nbut what does that mean and why do we want to do it?
\n
There's precious little on the net describing what the -n switch does. From the IDLE documentation:
\n\n\nIf IDLE is started with the -n command line switch it will run in a\nsingle process and will not create the subprocess which runs the RPC\nPython execution server. This can be useful if Python cannot create\nthe subprocess or the RPC socket interface on your platform. However,\nin this mode user code is not isolated from IDLE itself. Also, the\nenvironment is not restarted when Run/Run Module (F5) is selected. If\nyour code has been modified, you must reload() the affected modules and\nre-import any specific items (e.g. from foo import baz) if the changes\nare to take effect. For these reasons, it is preferable to run IDLE\nwith the default subprocess if at all possible.
\n
Which, I admit, doesn't help a huge amount...
\nFor the purposes of Python for Kids however, all you really need to know is that certain graphical libraries (such as turtle and, I seem to recall, tkinter) will exhibit weird behaviour (such as locking up/hanging) if you don't run IDLE using the -n switch.
", "date_published": "2013-08-27T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/07/09/tkinter-problems-on-the-raspberry-pi.html", "title": "Tkinter problems on the Raspberry Pi", "url": "https://jasonrbriggs.com/journal/2013/07/09/tkinter-problems-on-the-raspberry-pi.html", "content_text": "Ben writes:\n\n> _I am 12 and I am reading your book, Python for Kids._\n> _I have recently confronted a problem with the module tkinter. I have_\n> _recently got a rasberry pi to program on python._\n> _I am pretty sure that tkinter is already installed on python, but when I_\n> _run something like:_\n>\n> _def hello():_\n> _print('hello there')_\n> _from tkinter import *_\n> _tk = Tk()_\n> _btn = Button(tk, text='click me', command=hello)_\n> _btn.pack()_\n>\n> _There is nothing that pops up! I am frustrated and need help! Please help,_\n> _me and my father are new to linux by the way and don't know what to do._\n\nBen is using Debian Linux on his Raspberry Pi. After a bit of to-ing and fro-ing, we eventually found that tkinter was definitely installed, but it looks like (according to [this stackoverflow question](http://stackoverflow.com/questions/9048627/window-doesnt-appear-using-tkinter) that his father found) the tkinter window doesn't appear unless you use: `tk.mainloop()`.\n\nSo if you're trying the code on page 178 (for example) on a Pi, you might need to add one line to get it to work successfully:\n\n```python\n###\n>>> from tkinter import *\n>>> tk = Tk()\n>>> canvas = Canvas(tk, width=400, height=400)\n>>> canvas.pack()\n>>> canvas.create_arc(10, 10, 200, 80, extent=45, style=ARC)\n>>> canvas.create_arc(10, 80, 200, 160, extent=90, style=ARC)\n>>> canvas.create_arc(10, 160, 200, 240, extent=135, style=ARC)\n>>> canvas.create_arc(10, 240, 200, 320, extent=180, style=ARC)\n>>> canvas.create_arc(10, 320, 200, 400, extent=359, style=ARC)###\n>>> tk.mainloop()\n```", "content_html": "Ben writes:
\n\n\nI am 12 and I am reading your book, Python for Kids.\nI have recently confronted a problem with the module tkinter. I have\nrecently got a rasberry pi to program on python.\nI am pretty sure that tkinter is already installed on python, but when I\nrun something like:
\ndef hello():\n print('hello there')\nfrom tkinter import *\ntk = Tk()\nbtn = Button(tk, text='click me', command=hello)\nbtn.pack()
\nThere is nothing that pops up! I am frustrated and need help! Please help,\nme and my father are new to linux by the way and don't know what to do.
\n
Ben is using Debian Linux on his Raspberry Pi. After a bit of to-ing and fro-ing, we eventually found that tkinter was definitely installed, but it looks like (according to this stackoverflow question that his father found) the tkinter window doesn't appear unless you use: tk.mainloop()
.
So if you're trying the code on page 178 (for example) on a Pi, you might need to add one line to get it to work successfully:
\n###\n>>> from tkinter import *\n>>> tk = Tk()\n>>> canvas = Canvas(tk, width=400, height=400)\n>>> canvas.pack()\n>>> canvas.create_arc(10, 10, 200, 80, extent=45, style=ARC)\n>>> canvas.create_arc(10, 80, 200, 160, extent=90, style=ARC)\n>>> canvas.create_arc(10, 160, 200, 240, extent=135, style=ARC)\n>>> canvas.create_arc(10, 240, 200, 320, extent=180, style=ARC)\n>>> canvas.create_arc(10, 320, 200, 400, extent=359, style=ARC)###\n>>> tk.mainloop()
",
"date_published": "2013-07-09T23:52:53+00:00"
},
{
"id": "https://jasonrbriggs.com/journal/2013/07/30/python-kinderleicht.html",
"title": "Python Kinderleicht",
"url": "https://jasonrbriggs.com/journal/2013/07/30/python-kinderleicht.html",
"content_text": "[![Python Kinderleicht cover](https://jasonrbriggs.com/journal/2013/07/30/python-kinderleicht-small.jpg)](/journal/2013/07/30/python-kinderleicht.jpg) This arrived in the mail from [No Starch](http://nostarch.com) today.\n\nSehr cool!\n\nThe German translation of Python for Kids is available from the publisher [dpunkt verlag](https://www.dpunkt.de/buecher/4571/python-kinderleicht%21.html) and [amazon.de](http://www.amazon.de/Python-kinderleicht-Einfach-programmieren-lernen/dp/3864900220/) (probably others, but those were the first couple of links that popped up).",
"content_html": "This arrived in the mail from No Starch today.
\nSehr cool!
\nThe German translation of Python for Kids is available from the publisher dpunkt verlag and amazon.de (probably others, but those were the first couple of links that popped up).
", "date_published": "2013-06-30T10:00:00+01:00" }, { "id": "https://jasonrbriggs.com/journal/2013/06/28/on-feedly.html", "title": "On Feedly", "url": "https://jasonrbriggs.com/journal/2013/06/28/on-feedly.html", "content_text": "Rather than burning a significant amount of time rolling my own alternative to the soon-to-be-lamented [Google Reader](http://en.wikipedia.org/wiki/Google_Reader), I've been evaluating the various closed and open source options, finally settling on [Feedly](http://www.feedly.com).\n\n[![feedly error screen](https://jasonrbriggs.com/journal/2013/06/28/feedly1-small.png)](/journal/2013/06/28/feedly1.png) It's... okay... but the mobile app (at least the iPhone version) isn't... well... particularly mobile. Sure, it looks pretty, and for the always-connected user (those irradiated with 100% 3G coverage), perhaps its shortcomings are a little easier to bear. But I spend a significant chunk of commute-time, sitting on a train, with an internet connection that bounces like the proverbial yoyo. Instead of downloading all articles when there's a good internet connection, Feedly just downloads the current feed (possibly a side effect of the way I use it - I like to go to the individual feeds and read all articles in a section, rather than the mixed articles it presents in the _ALL_ tab). So on a typical commute home, I'm either presented with numerous error screens, or an interminable (so it feels) loading screen.\n\n[![feedly loading screen](https://jasonrbriggs.com/journal/2013/06/28/feedly2-small.png)](/journal/2013/06/28/feedly2.png) To make things worse, the iPhone app seems to forget that it just loaded something (not always, but enough to be annoying). So if I flip from Feedly, to iMessage, and then back again... once again I'm presented with the loading screen. The forgetfulness isn't limited to loading - it also affects articles I've already read (or already marked as read), which Feedly inconveniently forgets and I get the same set of articles again.\n\n[![feedly flick](https://jasonrbriggs.com/journal/2013/06/28/feedly3-small.png)](/journal/2013/06/28/feedly3.png) The interface seems a little inconsistent, as well. As I go through the articles in each feed, when I reach the end of the list, I'm presented with a large, friendly tick and a message telling me to \"Tap to mark all articles as read\". Which I do. The next feed appears and (after the loading screen) I flick the page up for the next article... except sometimes not. Despite the fact that there are plenty of unread articles, I can't flick to get to the next - I have to use the menu and find the next unread feed myself. Which might make sense if it was the last feed in a list sorted in alphabetical order. But it's not. So it makes no sense to me at all.\n\nSo, nice interface, but could use some work. A menu option, to download all articles when I've got a good connection (at home before leaving for work, for example). Remembering which article I was on last time, and not immediately trying to re-download just because the connection bounced in the meantime.\n\nStill... better thanRather than burning a significant amount of time rolling my own alternative to the soon-to-be-lamented Google Reader, I've been evaluating the various closed and open source options, finally settling on Feedly.
\nIt's... okay... but the mobile app (at least the iPhone version) isn't... well... particularly mobile. Sure, it looks pretty, and for the always-connected user (those irradiated with 100% 3G coverage), perhaps its shortcomings are a little easier to bear. But I spend a significant chunk of commute-time, sitting on a train, with an internet connection that bounces like the proverbial yoyo. Instead of downloading all articles when there's a good internet connection, Feedly just downloads the current feed (possibly a side effect of the way I use it - I like to go to the individual feeds and read all articles in a section, rather than the mixed articles it presents in the ALL tab). So on a typical commute home, I'm either presented with numerous error screens, or an interminable (so it feels) loading screen.
\nTo make things worse, the iPhone app seems to forget that it just loaded something (not always, but enough to be annoying). So if I flip from Feedly, to iMessage, and then back again... once again I'm presented with the loading screen. The forgetfulness isn't limited to loading - it also affects articles I've already read (or already marked as read), which Feedly inconveniently forgets and I get the same set of articles again.
\nThe interface seems a little inconsistent, as well. As I go through the articles in each feed, when I reach the end of the list, I'm presented with a large, friendly tick and a message telling me to \"Tap to mark all articles as read\". Which I do. The next feed appears and (after the loading screen) I flick the page up for the next article... except sometimes not. Despite the fact that there are plenty of unread articles, I can't flick to get to the next - I have to use the menu and find the next unread feed myself. Which might make sense if it was the last feed in a list sorted in alphabetical order. But it's not. So it makes no sense to me at all.
\nSo, nice interface, but could use some work. A menu option, to download all articles when I've got a good connection (at home before leaving for work, for example). Remembering which article I was on last time, and not immediately trying to re-download just because the connection bounced in the meantime.
\nStill... better than Reader nothing...
Update: turns out that Reeder coupled with Feedly in the backend (for the moment) is the ideal solution.
", "date_published": "2013-06-28T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/06/23/scratch-or-python.html", "title": "Scratch or Python?", "url": "https://jasonrbriggs.com/journal/2013/06/23/scratch-or-python.html", "content_text": "Marvin writes:\n\n> _I have a 10 year old son who is interested in programming. He really loves playing games so I thought_\n> _he should learn how they are created. I am a bit confused on which language to have him start._\n>\n> _My question is should he start with Scratch (and for how long?) or should I start him with the Python_\n> _language (with your book)? I've also heard about Ruby for Kids. Which is the easier path for him to start.?_\n>\n> _I will greatly appreciate you thoughts on how he should get started?_\n\nWell, by all means, my book... ツ\n\nBut to be entirely honest, it's a difficult question to answer. Some kids will find the visual nature of Scratch attractive. And it may be a natural progression to go from something like Scratch to a more traditional programming language (not something I have a lot of experience with, given I started with a traditional programming language when I was a kid). But, if he has a modicum of technical ability, and an interest in how games are really created, then learning a traditional programming language may be the better path.\n\nEither way, I don't think it will do any harm to start with Scratch, and progress to Python if he finds Scratch a little mundane - or vice versa, start with Python and go back to Scratch if he finds Python too advanced. However, in terms of Ruby, I can't really comment, as it's not a language I have much experience with.\n\nNot sure that particularly helps, but good luck anyway.", "content_html": "Marvin writes:
\n\n\nI have a 10 year old son who is interested in programming. He really loves playing games so I thought\nhe should learn how they are created. I am a bit confused on which language to have him start.
\nMy question is should he start with Scratch (and for how long?) or should I start him with the Python\nlanguage (with your book)? I've also heard about Ruby for Kids. Which is the easier path for him to start.?
\nI will greatly appreciate you thoughts on how he should get started?
\n
Well, by all means, my book... ツ
\nBut to be entirely honest, it's a difficult question to answer. Some kids will find the visual nature of Scratch attractive. And it may be a natural progression to go from something like Scratch to a more traditional programming language (not something I have a lot of experience with, given I started with a traditional programming language when I was a kid). But, if he has a modicum of technical ability, and an interest in how games are really created, then learning a traditional programming language may be the better path.
\nEither way, I don't think it will do any harm to start with Scratch, and progress to Python if he finds Scratch a little mundane - or vice versa, start with Python and go back to Scratch if he finds Python too advanced. However, in terms of Ruby, I can't really comment, as it's not a language I have much experience with.
\nNot sure that particularly helps, but good luck anyway.
", "date_published": "2013-06-23T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/06/05/problems-installing-python.html", "title": "Problems installing Python", "url": "https://jasonrbriggs.com/journal/2013/06/05/problems-installing-python.html", "content_text": "Chana writes:\n\n> _Python does not install on my computer, and I'm not sure why._\n>\n> _Windows 7 Home Premium 64-bit operating system_\n>\n> _Everything works fine until you get to the part that says \"Please wait while_\n> _the installer installs python...\" After about half an hour, a little window pops up_\n> _that says that the installer is no longer responding._\n\nAccording to this page... [http://superuser.com/questions/168561/python-wont-install-on-windows-7](http://superuser.com/questions/168561/python-wont-install-on-windows-7)... you should try disabling UAC. I'm not a home Windows user, but a quick google found this: [http://www.howtogeek.com/howto/windows-vista/disable-user-account-control-uac-the-easy-way-on-windows-vista/](http://www.howtogeek.com/howto/windows-vista/disable-user-account-control-uac-the-easy-way-on-windows-vista/). Hopefully that fixes the problem.", "content_html": "Chana writes:
\n\n\nPython does not install on my computer, and I'm not sure why.
\nWindows 7 Home Premium 64-bit operating system
\nEverything works fine until you get to the part that says \"Please wait while\nthe installer installs python...\" After about half an hour, a little window pops up\nthat says that the installer is no longer responding.
\n
According to this page... http://superuser.com/questions/168561/python-wont-install-on-windows-7... you should try disabling UAC. I'm not a home Windows user, but a quick google found this: http://www.howtogeek.com/howto/windows-vista/disable-user-account-control-uac-the-easy-way-on-windows-vista/. Hopefully that fixes the problem.
", "date_published": "2013-06-05T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/06/04/oreilly-media-discount.html", "title": "O'Reilly Media Discounts", "url": "https://jasonrbriggs.com/journal/2013/06/04/oreilly-media-discount.html", "content_text": "Apparently [Python for Kids](https://jasonrbriggs.com/python-for-kids) is featured in [O'Reilly Media](https://twitter.com/OReillyMedia)'s \"Learn to Program ebooks\" promotion (save 50% on introductory programming ebooks). More details can be found [here](http://oreil.ly/11hY4B0).", "content_html": "Apparently Python for Kids is featured in O'Reilly Media's \"Learn to Program ebooks\" promotion (save 50% on introductory programming ebooks). More details can be found here.
", "date_published": "2013-06-04T23:52:53+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/05/26/lander-solution-posted.html", "title": "Lander Solution Posted", "url": "https://jasonrbriggs.com/journal/2013/05/26/lander-solution-posted.html", "content_text": "A partial solution to the [Lunar Lander 'Programming Puzzle'](https://jasonrbriggs.com/python-for-kids/puzzles/project1-lander.html) has just been [posted](https://jasonrbriggs.com/python-for-kids/puzzles/project1-lander-solution.html).\n\n", "content_html": "A partial solution to the Lunar Lander 'Programming Puzzle' has just been posted.
", "date_published": "2013-05-26T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/05/19/one-versus-two-underscores.html", "title": "One versus two underscores", "url": "https://jasonrbriggs.com/journal/2013/05/19/one-versus-two-underscores.html", "content_text": "Omer writes:\n\n> _I am currently on Chapter 13 and I have come across a problem that I cannot seem to figure out._\n> _I am in the section 'Creating the Ball Class'. I wrote the code the way that you have described_\n> _in the book, and I am getting the following error:_\n>\n> _Traceback (most recent call last):_\n> _File \"C:/Users/Omer/Desktop/Master Functions/PaddleBall.py\", line 22, in <module>_\n> _ball = Ball(canvas, 'red')_\n> _TypeError: object.\\_\\_new\\_\\_() takes no parameters_\n>\n> _However, when I copied the code from your website, it worked perfectly. I put my code and your code side_\n> _by side and I cannot seem to figure out where the mistake is. Can you help me figure this out._\n\nIt's easy to miss something when you're manually comparing two files. The best way to do this sort of thing is to use a [diff](http://en.wikipedia.org/wiki/Diff) tool. You're using Windows, so something like [winmerge](http://winmerge.org) would do the trick.\nIn any case, when I diff the files you sent using the command line diff tool, I see the following difference:\n\n```\n14c14\n< def _init_(self, canvas, color):\n---\n> def __init__(self, canvas, color):\n```\n\nSo in your code you've got a single underscore on either side of `init` - which explains the error you're getting. Because you haven't defined the `__init__` function correctly, Python assumes a default with no parameters. Fix that, and the code should work as expected. Good luck!\n\n_Addendum (for anyone searching for similar errors): on Windows, you'll probably get a message like \"`TypeError: Ball() takes no arguments`\", but ultimately the cause is exactly the same._", "content_html": "Omer writes:
\n\n\nI am currently on Chapter 13 and I have come across a problem that I cannot seem to figure out.\nI am in the section 'Creating the Ball Class'. I wrote the code the way that you have described\nin the book, and I am getting the following error:
\nTraceback (most recent call last):\n File \"C:/Users/Omer/Desktop/Master Functions/PaddleBall.py\", line 22, in <module>\n ball = Ball(canvas, 'red')\n TypeError: object.__new__() takes no parameters
\nHowever, when I copied the code from your website, it worked perfectly. I put my code and your code side\nby side and I cannot seem to figure out where the mistake is. Can you help me figure this out.
\n
It's easy to miss something when you're manually comparing two files. The best way to do this sort of thing is to use a diff tool. You're using Windows, so something like winmerge would do the trick.\nIn any case, when I diff the files you sent using the command line diff tool, I see the following difference:
\n14c14\n< def _init_(self, canvas, color):\n---\n> def __init__(self, canvas, color):
\nSo in your code you've got a single underscore on either side of init
- which explains the error you're getting. Because you haven't defined the __init__
function correctly, Python assumes a default with no parameters. Fix that, and the code should work as expected. Good luck!
Addendum (for anyone searching for similar errors): on Windows, you'll probably get a message like \"TypeError: Ball() takes no arguments
\", but ultimately the cause is exactly the same.
Evan writes:
\n\n\nI have a Windows 8 PC, and have installed Python 3.3 onto it, and worked my way up to the last part of chapter 9 in your\nbook with no major problems. But now I am stuck in the last part of chapter 9. The first time I tried to save a notepad\ntxt file to the C: location, access was denied, because the user account I was using was not the dominant user account.\nI fixed this by running the notepad as the administrator, and was able to save the txt file to the C: location.\nOpening and printing the contents of the txt file worked fine after that. My next problem (and still is a problem)\nwas writing to the text file. The first error message said access was denied. I fixed this also by going to the\nadministrator's user account and allowed the user settings I was working on to have almost complete control over all\nthe C: location. Now when I try to write to the txt file, I get a different error:\n\"OSError: [Errno 22] Invalid argument: 'c:\\myfile.txt'.\nPlease help me!
\n
Hi Evan. The final error you're getting is generally caused by an invalid filename (for example, if you had two colons rather than one) - but I don't see that problem in the example you sent. So I'm not quite sure what's gone wrong there.
\nIn terms of the example in the book, I've added a new entry in the errata (see the section Page 123). The directions should instead tell you to save the file to your user directory - something like: c:\\\\Users\\\\Evan
- rather than to c:\\
. Check the errata and hopefully that should work for you.
Michal writes:
\n\n\nMy son has found a problem. It is regarding:
\nfrom tkinter import *
\n
\ncolorchooser.askcolor()It is not working and I cannot help him. On the python shell he gets an error:
\nTraceback (most recent call last):
\n
\nFile \"colorrect.py\", line 2, in <module>
\ncolorchooser.askcolor()
\nNameError: name 'colorchooser' is not definedCould you help please.
\n
This is an odd one. If I try the code in the Shell, the color chooser is available as expected:
\n\nBut if I try the same code in the command-line console, I get a similar error:
\n\nThe only way I can reproduce the problem in the Shell is when I don't run it in \"No Subprocess\" mode - that's if you don't follow the installation instructions, in Chapter 1 of the book, and just run the Shell/IDLE as it was installed (without modifying the shortcut):
\n\nYou can get around this, by directly importing the colorchooser module like so:
\n>>> import tkinter.colorchooser\n>>> tkinter.colorchooser.askcolor()
\nBut you'll probably hit problems if you try to call the askcolor
function (the second line in that snippet of code above).
All of which is rather messy and confusing. My suggestion would be to make sure you see the \"No Subprocess\" message when you run IDLE, and if not, revisit Chapter 1. If you do see the message on startup, and still get the error (which I haven't managed to do, but I'm guessing might be possible), try the sample code above, and see if that works for you. Good luck!
\nMore information updated July 2020 here.
", "date_published": "2013-05-01T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/04/24/good-luck.html", "title": "Good luck", "url": "https://jasonrbriggs.com/journal/2013/04/24/good-luck.html", "content_text": "To the (I assume) wannabe-hackers who, according to my web server logs, are trying to access various combinations of wp-admin, wp-login and other types of login page... good luck with that! ツ", "content_html": "To the (I assume) wannabe-hackers who, according to my web server logs, are trying to access various combinations of wp-admin, wp-login and other types of login page... good luck with that! ツ
", "date_published": "2013-04-24T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/04/17/python-on-the-web.html", "title": "Python on the Web?", "url": "https://jasonrbriggs.com/journal/2013/04/17/python-on-the-web.html", "content_text": "Dean writes:\n\n> _I'm 13, I live in the US, and I just finished reading your excellent book \"Python for Kids\"._\n> _After I finished the book I had two questions. First I was curious if it is possible to put_\n> _a python game on a website to play? The other question I had was what was the hardest project_\n> _you have ever worked on, how long did it take you, and what language was it in?_\n\nThere are a few implementations of Python that will work inside the browser, but as far as I know they don't support all of Python's features (such as the tkinter module, or PyGame, for example). So it would be rather difficult to write a game that could be played on a website (in my opinion). If that's something you want to do, you'd be better off learning Javascript (the standard programming language used in all browsers). If you google for \"javascript and html5 games development\", you'll find a lot of information out there. Luckily, once you've learned one programming language, it's a lot easier to learn the next.\n\nIn terms of hardest project, that's a difficult question to answer. I've worked on projects which were hard because the amount of code in the application was huge, and because there were a lot of \"moving parts\" - lots of communication between different systems. In terms of complicated systems, I recall one project (which I spent about 18 months on with a team of 8 or 9 people) where I had to write the code for very complicated graphical reports -- that was hard because I had to remember mathematics I learned years before (the programming language in that case was Java and some Python as well).\n\nHope that helps.", "content_html": "Dean writes:
\n\n\nI'm 13, I live in the US, and I just finished reading your excellent book \"Python for Kids\".\nAfter I finished the book I had two questions. First I was curious if it is possible to put\na python game on a website to play? The other question I had was what was the hardest project\nyou have ever worked on, how long did it take you, and what language was it in?
\n
There are a few implementations of Python that will work inside the browser, but as far as I know they don't support all of Python's features (such as the tkinter module, or PyGame, for example). So it would be rather difficult to write a game that could be played on a website (in my opinion). If that's something you want to do, you'd be better off learning Javascript (the standard programming language used in all browsers). If you google for \"javascript and html5 games development\", you'll find a lot of information out there. Luckily, once you've learned one programming language, it's a lot easier to learn the next.
\nIn terms of hardest project, that's a difficult question to answer. I've worked on projects which were hard because the amount of code in the application was huge, and because there were a lot of \"moving parts\" - lots of communication between different systems. In terms of complicated systems, I recall one project (which I spent about 18 months on with a team of 8 or 9 people) where I had to write the code for very complicated graphical reports -- that was hard because I had to remember mathematics I learned years before (the programming language in that case was Java and some Python as well).
\nHope that helps.
", "date_published": "2013-04-17T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/04/14/solution-6.html", "title": "Solution 6", "url": "https://jasonrbriggs.com/journal/2013/04/14/solution-6.html", "content_text": "The solution to [programming puzzle #6](https://jasonrbriggs.com/python-for-kids/puzzles/puzzle6.html) has just been [posted](https://jasonrbriggs.com/python-for-kids/puzzles/puzzle6-solution.html).", "content_html": "The solution to programming puzzle #6 has just been posted.
", "date_published": "2013-04-14T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/04/03/between-giants.html", "title": "Between Giants", "url": "https://jasonrbriggs.com/journal/2013/04/03/between-giants.html", "content_text": "Similar in scale to a [gnat between two giants](https://twitter.com/nathanp/status/318921317657243648)...? ツ", "content_html": "Similar in scale to a gnat between two giants...? ツ
", "date_published": "2013-04-03T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/03/17/synchronisation.html", "title": "Synchronisation", "url": "https://jasonrbriggs.com/journal/2013/03/17/synchronisation.html", "content_text": "About the only thing I actually use [Google Reader](http://googleblog.blogspot.co.uk/2013/03/a-second-spring-of-cleaning.html) for, is synchronisation between devices. I use both [Net News Wire](http://netnewswireapp.com) and [Feeddler](http://www.chebinliu.com/projects/iphone/feeddler-rss-reader/) -- neither of which are perfect, but the magazine-style RSS readers (such as Feedly, and the like) don't really suit my usage patterns.\n\nI wonder if the answer (for myself, at least) is a basic [web-based](http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#offline) reader, which uses [dropbox](https://github.com/dropbox/dropbox-js) for storing synchronisation data. With about 5MB of [localStorage](http://diveintohtml5.info/storage.html), I could also possibly fix one of my bug bears with the clients I use at the moment - offline download of some content (for those train trips where the connection drops like a yoyo). Using the iPhone's safari browser for the reader itself would fix the other problem I have (specifically with NNW) -- poor download and page rendering performance.\n\nThere's my spec ↑... now I just need to find the time to develop it... (before July)\n\n[Update](https://jasonrbriggs.com/journal/2013/06/28/on-feedly.html)", "content_html": "About the only thing I actually use Google Reader for, is synchronisation between devices. I use both Net News Wire and Feeddler -- neither of which are perfect, but the magazine-style RSS readers (such as Feedly, and the like) don't really suit my usage patterns.
\nI wonder if the answer (for myself, at least) is a basic web-based reader, which uses dropbox for storing synchronisation data. With about 5MB of localStorage, I could also possibly fix one of my bug bears with the clients I use at the moment - offline download of some content (for those train trips where the connection drops like a yoyo). Using the iPhone's safari browser for the reader itself would fix the other problem I have (specifically with NNW) -- poor download and page rendering performance.
\nThere's my spec ↑... now I just need to find the time to develop it... (before July)
\n", "date_published": "2013-03-17T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/03/13/programmer-humour.html", "title": "Programmer Humour", "url": "https://jasonrbriggs.com/journal/2013/03/13/programmer-humour.html", "content_text": "Thanks very much, [Randall](http://xkcd.com/1185/)...\n\n[![ineffective sorts](https://jasonrbriggs.com/journal/2013/03/13/ineffective-sorts-small.png)](/journal/2013/03/13/ineffective-sorts.png)\n \n\n...you made me laugh out loud on the train, so now I look like a nutball.\nツ", "content_html": "Thanks very much, Randall...
\n\n...you made me laugh out loud on the train, so now I look like a nutball.\nツ
", "date_published": "2013-03-13T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/03/08/belated.html", "title": "Belated...", "url": "https://jasonrbriggs.com/journal/2013/03/08/belated.html", "content_text": "Rather belatedly... the solution to Puzzle #5 was [posted](https://jasonrbriggs.com/python-for-kids/puzzles/puzzle5-solution.html) a few days ago. [Puzzle #6](https://jasonrbriggs.com/python-for-kids/puzzles/puzzle6.html) is now also available.\n\nAlso rather belatedly, Dave Winer has an interesting [take](http://threads2.scripting.com/2013/february/whyYouShouldLearnToCode) on the recent [code.org](http://code.org) promotional video. Stand out quote:\n\n > _Primarily you should do it (ed: programming) because you love it,_\n > _because it's fun -- because it's wonderful to create machines_\n > _with your mind. Hugely empowering. Emotionally gratifying._\n > _Software is math-in-motion. It's a miracle of the mind._\n > _And if you can do it, really well, there's absolutely nothing like it._", "content_html": "Rather belatedly... the solution to Puzzle #5 was posted a few days ago. Puzzle #6 is now also available.
\nAlso rather belatedly, Dave Winer has an interesting take on the recent code.org promotional video. Stand out quote:
\n\n", "date_published": "2013-03-08T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/03/06/solace.html", "title": "Solace", "url": "https://jasonrbriggs.com/journal/2013/03/06/solace.html", "content_text": "While listening to [Solace](http://www.tettix.net/albums/solace.html), I can't help be struck by the thought that it would sound brilliant performed by a full symphony orchestra (probably with electric guitar accompaniment). Something I'd pay to listen to...\n\n(via [BoingBoing](http://boingboing.net/2013/02/19/solace-why-make-a-soundtrack.html))", "content_html": "Primarily you should do it (ed: programming) because you love it,\nbecause it's fun -- because it's wonderful to create machines\nwith your mind. Hugely empowering. Emotionally gratifying.\nSoftware is math-in-motion. It's a miracle of the mind.\nAnd if you can do it, really well, there's absolutely nothing like it.
\n
While listening to Solace, I can't help be struck by the thought that it would sound brilliant performed by a full symphony orchestra (probably with electric guitar accompaniment). Something I'd pay to listen to...
\n(via BoingBoing)
", "date_published": "2013-03-06T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/02/20/pfk-errata.html", "title": "PFK Errata", "url": "https://jasonrbriggs.com/journal/2013/02/20/pfk-errata.html", "content_text": "Piotr Słowik writes:\n\n> _I'm learning how to code from your book. It's great! First time in my life I'm starting to understand how to write code_\n> _and make it work ;) You're the first person whose teachings make sense to me!_\n>\n> _But I have problem with this example:_\n>\n> _\\>\\>\\> v = sys.stdin.readline(13)_\n> _He who laughs last thinks slowest_\n> _\\>\\>\\> print(v)_\n> _He who laughs_\n>\n> _Whatever I do I get this error:_\n>\n> _readline() takes 1 positional argument but 2 were given_\n>\n> _I'm using Python 3.3. Please, help._\n\nThanks for the email Piotr. It looks like you've found the first 'bug' in the book. That example definitely works -- but it doesn't work in the Python Shell. If you try in the Console, you won't get the error.\n\nThe reason for the difference is that the Shell does some magic to replace the `stdin` object with a version of its own -- and its version of the `readline` function doesn't have a parameter for the maximum number of characters (hence you get an unexpected error message).\n\nI've added this to the [errata page](https://jasonrbriggs.com/python-for-kids/errata.html) accordingly.", "content_html": "Piotr Słowik writes:
\n\n\nI'm learning how to code from your book. It's great! First time in my life I'm starting to understand how to write code\nand make it work ;) You're the first person whose teachings make sense to me!
\nBut I have problem with this example:
\n>>> v = sys.stdin.readline(13)\nHe who laughs last thinks slowest\n>>> print(v)\nHe who laughs
\nWhatever I do I get this error:
\nreadline() takes 1 positional argument but 2 were given
\nI'm using Python 3.3. Please, help.
\n
Thanks for the email Piotr. It looks like you've found the first 'bug' in the book. That example definitely works -- but it doesn't work in the Python Shell. If you try in the Console, you won't get the error.
\nThe reason for the difference is that the Shell does some magic to replace the stdin
object with a version of its own -- and its version of the readline
function doesn't have a parameter for the maximum number of characters (hence you get an unexpected error message).
I've added this to the errata page accordingly.
", "date_published": "2013-02-20T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/02/12/puzzle-updates.html", "title": "Puzzle Updates", "url": "https://jasonrbriggs.com/journal/2013/02/12/puzzle-updates.html", "content_text": "\nThe solution to Programming Puzzle #4 has been [posted](https://jasonrbriggs.com/python-for-kids/puzzle4.html), and you can also find a new puzzle added [here](https://jasonrbriggs.com/python-for-kids/puzzle5.html).\n", "content_html": "The solution to Programming Puzzle #4 has been posted, and you can also find a new puzzle added here.
", "date_published": "2013-02-12T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/01/31/front-page.html", "title": "The Front Page", "url": "https://jasonrbriggs.com/journal/2013/01/31/front-page.html", "content_text": "[![raspberrypi.org](https://jasonrbriggs.com/journal/2013/01/31/raspberrypi.org-small.png)](/journal/2013/01/31/raspberrypi.org.png) Very cool. The front page of [raspberrypi.org](http://raspberrypi.org).\n\nOfficially geeked out.\n\n", "content_html": "Very cool. The front page of raspberrypi.org.
\nOfficially geeked out.
", "date_published": "2013-01-31T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/01/25/stickman-elevators.html", "title": "Stickman Elevators", "url": "https://jasonrbriggs.com/journal/2013/01/25/stickman-elevators.html", "content_text": "Henry Angeles writes:\n\n> _I'm not a programmer, so when my kid asked me to make an elevator in the stickman game I totally failed._\n> _I can get the platform to move up and down, but when the elevator starts going up with the stickman on it,_\n> _hilarity ensues._\n\n> _I guess at the end of the day i'm asking how this can be done. Thanks for your time._\n\nI'm not surprised you found it difficult. It caused a fair amount of head scratching until I realised the trick to getting this working. If you used the code for the horizontal platforms in [PythonForKidsSolutions.pdf](http://nostarch.com/download/PythonForKidsSolutions.pdf) as the basis for your elevator, your stick figure probably slips through the platform as soon as he touches it (or potentially rockets off up the screen depending upon your code). The elevator moves at a different speed to the stick figure, so you need to match that speed when the figure lands on the platform - and you can't rely on the basic collision detection code as it's written in that example.\n\nA new programming puzzle, for this, has been added to the [puzzles page](https://jasonrbriggs.com/python-for-kids/puzzles.html) - check back in a week or two for the full solution.", "content_html": "Henry Angeles writes:
\n\n\nI'm not a programmer, so when my kid asked me to make an elevator in the stickman game I totally failed.\nI can get the platform to move up and down, but when the elevator starts going up with the stickman on it,\nhilarity ensues.
\nI guess at the end of the day i'm asking how this can be done. Thanks for your time.
\n
I'm not surprised you found it difficult. It caused a fair amount of head scratching until I realised the trick to getting this working. If you used the code for the horizontal platforms in PythonForKidsSolutions.pdf as the basis for your elevator, your stick figure probably slips through the platform as soon as he touches it (or potentially rockets off up the screen depending upon your code). The elevator moves at a different speed to the stick figure, so you need to match that speed when the figure lands on the platform - and you can't rely on the basic collision detection code as it's written in that example.
\nA new programming puzzle, for this, has been added to the puzzles page - check back in a week or two for the full solution.
", "date_published": "2013-01-25T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/01/21/puzzle2-solution.html", "title": "Puzzles 2 and 3", "url": "https://jasonrbriggs.com/journal/2013/01/21/puzzle2-solution.html", "content_text": "\nThe solution to [Programming Puzzle 2](https://jasonrbriggs.com/python-for-kids/puzzle2.html) has just been added to the puzzle's page, and challenge number 3 has been [posted](https://jasonrbriggs.com/python-for-kids/puzzle3.html).", "content_html": "The solution to Programming Puzzle 2 has just been added to the puzzle's page, and challenge number 3 has been posted.
", "date_published": "2013-01-21T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/01/10/raspberry-pi.html", "title": "Python for Kids on the Raspberry Pi", "url": "https://jasonrbriggs.com/journal/2013/01/10/raspberry-pi.html", "content_text": "I finally managed to find enough bits-and-pieces to get a [Raspberry Pi](http://www.raspberrypi.org) (borrowed from a friend - thanks Matt!) up and running, in order to test out the code from [Python for Kids](https://jasonrbriggs.com/python-for-kids). A USB charger for an old Nokia phone, a somewhat dodgy-looking USB power adaptor from the bottom of a cobweb-filled box in the back room, a wireless mouse (the base for which had managed to hide itself on the opposite side of the house), a bent network cable (surprisingly still functional), and a [powerline](http://en.wikipedia.org/wiki/Power_line_communication#Home_networking_.28LAN.29) adaptor scavenged from the TV. In the end the only thing missing was a USB keyboard, which finally arrived in the mail this morning.\n\n[![Raspbian menu](https://jasonrbriggs.com/journal/2013/01/10/rpi-menu-small.png)](/journal/2013/01/10/rpi-menu.png) It looks like all the code works fine, and Python3 is installed by default on the [Raspbian operating system](http://www.raspbian.org), so there's not a lot required to install out of the box. There is one thing to be aware of - do not use the IDLE3 icon which is on the desktop by default (at least not when you're running the graphics code in the book). Instead, go to the _Other_ menu, and choose _IDLE (Python 3.2)_ (click on the screenshot to see what you should be looking for). This runs IDLE in \"No subprocess\" mode, so modules such as [turtle](http://docs.python.org/3.2/library/turtle.html) will run correctly.\n\nHowever, to use GIMP (the graphics program we use in Chapter 15), you will need to install it first:\n\n1. Make sure your Raspberry Pi is connected to the internet\n2. Open a terminal (select the _Other_ menu, and then _LXTerminal_)\n3. Update the package list (might not be necessary, but just in case) by entering the following command:\n `sudo apt-get update`\n4. Once completed, install GIMP by running this command:\n `sudo apt-get install gimp`\n\nAfter installation, you'll find a new menu option in the _Graphics_ menu: _GNU Image Manipulation Program_.\n\nThat should be all you need to get started with the Raspberry Pi.\n\n", "content_html": "I finally managed to find enough bits-and-pieces to get a Raspberry Pi (borrowed from a friend - thanks Matt!) up and running, in order to test out the code from Python for Kids. A USB charger for an old Nokia phone, a somewhat dodgy-looking USB power adaptor from the bottom of a cobweb-filled box in the back room, a wireless mouse (the base for which had managed to hide itself on the opposite side of the house), a bent network cable (surprisingly still functional), and a powerline adaptor scavenged from the TV. In the end the only thing missing was a USB keyboard, which finally arrived in the mail this morning.
\nIt looks like all the code works fine, and Python3 is installed by default on the Raspbian operating system, so there's not a lot required to install out of the box. There is one thing to be aware of - do not use the IDLE3 icon which is on the desktop by default (at least not when you're running the graphics code in the book). Instead, go to the Other menu, and choose IDLE (Python 3.2) (click on the screenshot to see what you should be looking for). This runs IDLE in \"No subprocess\" mode, so modules such as turtle will run correctly.
\nHowever, to use GIMP (the graphics program we use in Chapter 15), you will need to install it first:
\nsudo apt-get update
sudo apt-get install gimp
After installation, you'll find a new menu option in the Graphics menu: GNU Image Manipulation Program.
\nThat should be all you need to get started with the Raspberry Pi.
", "date_published": "2013-01-10T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2013/01/01/puzzle1-solution.html", "title": "Puzzle 1 Solution", "url": "https://jasonrbriggs.com/journal/2013/01/01/puzzle1-solution.html", "content_text": "Happy New Year!\n\nThe solution to [Programming Puzzle 1](https://jasonrbriggs.com/python-for-kids/puzzle1.html) has been added to the puzzle page - actually it was updated just before Christmas, but I've been entirely tooHappy New Year!
\nThe solution to Programming Puzzle 1 has been added to the puzzle page - actually it was updated just before Christmas, but I've been entirely too lazy busy to post about it. ツ
We went to Rome over the weekend. Despite the weather (mild but wet), gelato seemed one of the higher priorities - a task that was more difficult than you might expect, when you want to go to one of the more famous Italian ice cream parlours, and you're relying on the slightly oddly printed tourist maps (with occasional irritatingly positioned advertising boxes). \nApple's Maps isn't bad, at a high level, and I like the way it saves prior searches, but in order to see the street names, you need to zoom in far too close to get a good idea of where you're going next (at times).
\nGoogle Maps doesn't save prior searches (unless you're logged in, I believe), but it offers a number of alternative walking routes (useful for tourist wanderings), and seems to do a better job of highlighting street names. In addition, with data roaming switched off, it didn't stumble after first downloading the maps on Wi-Fi - I don't think Apple Maps was quite as good. I haven't quite dragged it to my front screen to replace Maps yet - but I'm wavering...
", "date_published": "2012-12-19T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/12/11/two-years-of-effort.html", "title": "Two years of effort", "url": "https://jasonrbriggs.com/journal/2012/12/11/two-years-of-effort.html", "content_text": "\n[![Python for Kids in box](https://jasonrbriggs.com/journal/2012/12/11/python-for-kids-small.png)](/journal/2012/12/11/python-for-kids-medium.png) My author copies arrived from [No Starch](http://nostarch.com/pythonforkids) today - the culmination of two years of not-an-inconsequential amount of effort.\n\nIf you happen to have ordered a copy, here's hoping it arrives in time to stuff the Christmas stocking.\n", "content_html": "My author copies arrived from No Starch today - the culmination of two years of not-an-inconsequential amount of effort.
\nIf you happen to have ordered a copy, here's hoping it arrives in time to stuff the Christmas stocking.
", "date_published": "2012-12-11T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/12/09/new-programming-puzzle.html", "title": "New Programming Puzzle", "url": "https://jasonrbriggs.com/journal/2012/12/09/new-programming-puzzle.html", "content_text": "![puzzle image](https://jasonrbriggs.com/journal/2012/12/09/puzzle.png) A [new programming puzzle](https://jasonrbriggs.com/python-for-kids/puzzles.html) has been added today. This one is a bit more difficult than the last - the actual solution isn't all that complicated, but it does require a bit of lateral thinking.\n", "content_html": "A new programming puzzle has been added today. This one is a bit more difficult than the last - the actual solution isn't all that complicated, but it does require a bit of lateral thinking.
", "date_published": "2012-12-09T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/11/13/engineering.html", "title": "Engineering... or programming?", "url": "https://jasonrbriggs.com/journal/2012/11/13/engineering.html", "content_text": "[Are Programmers Engineers?](http://www.ericsink.com/Are_Programmers_Engineers.html)", "content_html": "", "date_published": "2012-11-13T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/10/22/scratch-the-kindle.html", "title": "Scratch the Kindle?", "url": "https://jasonrbriggs.com/journal/2012/10/22/scratch-the-kindle.html", "content_text": "\nI had thought that, at some point, I would consider buying a Kindle. If this Boing Boing [story](http://boingboing.net/2012/10/22/kindle-user-claims-amazon-dele.html) proves to be true, I'm not so sure. Certainly, in a feature-by-feature comparison with the [competitors](http://en.wikipedia.org/wiki/Comparison_of_e-book_readers), it's something to bear in mind...\n\nRef #1: [http://boingboing.net/2012/10/22/kindle-user-claims-amazon-dele.html](http://boingboing.net/2012/10/22/kindle-user-claims-amazon-dele.html)\nRef #2: [http://www.bekkelund.net/2012/10/22/outlawed-by-amazon-drm/](http://www.bekkelund.net/2012/10/22/outlawed-by-amazon-drm/)", "content_html": "I had thought that, at some point, I would consider buying a Kindle. If this Boing Boing story proves to be true, I'm not so sure. Certainly, in a feature-by-feature comparison with the competitors, it's something to bear in mind...
\nRef #1: http://boingboing.net/2012/10/22/kindle-user-claims-amazon-dele.html\nRef #2: http://www.bekkelund.net/2012/10/22/outlawed-by-amazon-drm/
", "date_published": "2012-10-22T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/09/23/on-ios6-maps.html", "title": "On iOS 6 Maps", "url": "https://jasonrbriggs.com/journal/2012/09/23/on-ios6-maps.html", "content_text": "![iOS 6 map showing Bangkok streets](https://jasonrbriggs.com/journal/2012/09/23/ios6-map.png) One interesting thing I've noticed with the new Maps app in iOS 6 is that (unlike Google Maps) there's no longer an English translation for streets in Bangkok (or if there is I haven't found how to switch it on yet). I've tried searching for the common English spellings for some streets and it appears to work - but doesn't seem quite as accurate. And if you don't read Thai, when Maps isn't showing you the correct street, you won't be able to tell anyway. So, much as I like the look of Apple's efforts, I think what I really want is a native Google Maps app, with offline map storage...\n\nUpdate: although it [sounds like](http://appleinsider.com/articles/12/10/05/apples-new-ios-6-maps-support-automatic-offline-use-for-a-wide-area) perhaps iOS Maps will be better for offline navigation anyway.", "content_html": "One interesting thing I've noticed with the new Maps app in iOS 6 is that (unlike Google Maps) there's no longer an English translation for streets in Bangkok (or if there is I haven't found how to switch it on yet). I've tried searching for the common English spellings for some streets and it appears to work - but doesn't seem quite as accurate. And if you don't read Thai, when Maps isn't showing you the correct street, you won't be able to tell anyway. So, much as I like the look of Apple's efforts, I think what I really want is a native Google Maps app, with offline map storage...
\nUpdate: although it sounds like perhaps iOS Maps will be better for offline navigation anyway.
", "date_published": "2012-09-23T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/08/04/trs-80.html", "title": "TRS-80", "url": "https://jasonrbriggs.com/journal/2012/08/04/trs-80.html", "content_text": "\n![TRS-80](https://jasonrbriggs.com/journal/2012/08/04/trs-80.png) The TRS-80 is the computer that got me started (over 30 years ago). It's funny that even up till now, I hadn't realised that the \"TRS\" (pretty obviously) stood for Tandy Radio Shack. \n \n[Please Don't Call It Trash-80: A 35th Anniversary Salute to Radio Shack's TRS-80](http://techland.time.com/2012/08/03/trs-80)", "content_html": "The TRS-80 is the computer that got me started (over 30 years ago). It's funny that even up till now, I hadn't realised that the \"TRS\" (pretty obviously) stood for Tandy Radio Shack.
\nPlease Don't Call It Trash-80: A 35th Anniversary Salute to Radio Shack's TRS-80
", "date_published": "2012-08-04T23:52:52+00:00" }, { "id": "https://jasonrbriggs.com/journal/2012/06/01/learning-to-code.html", "title": "Learning to code?", "url": "https://jasonrbriggs.com/journal/2012/06/01/learning-to-code.html", "content_text": "\nBack in 2006, author David Brin lamented the lack of a good way to get kids into programming (Brin's article was actually my impetus to start writing an e-book for teaching small humans to code): [Why Johnny can't code](http://www.salon.com/2006/09/14/basic_2/).\n\nCompare with the situation now...\n\nJohn Naughton thinks kids should be taught to code in school. Given what is taught at the moment in UK schools for ICT, this isn't a bad idea: [Why Kids Should Be Taught Code](http://www.guardian.co.uk/education/2012/mar/31/why-kids-should-be-taught-code).\n\nDan Rowinski, of ReadWriteWeb, writes about a movement forming in the programming community around the idea of a new standard of literacy: [Computer Programming for All: A New Standard of Literacy](http://www.readwriteweb.com/hack/2012/05/computer-programming-for-all-a-new-standard-of-literacy.php).\n\nMatthew Murray, of ExtremeTech, has a few doubts, and thinks there needs to be more focus on the basics (imagination, logic, reasoning, and problem solving): [Should Kids Learn To Code?](http://www.extremetech.com/computing/115939-should-kids-learn-to-code)\n\nJeff Atwood (also linked in the RWW article) thinks that you should learn to code for the right reasons, or else focus on more important skills: [Please don't learn to code](http://www.codinghorror.com/journal/2012/05/please-dont-learn-to-code.html).\n\n", "content_html": "Back in 2006, author David Brin lamented the lack of a good way to get kids into programming (Brin's article was actually my impetus to start writing an e-book for teaching small humans to code): Why Johnny can't code.
\nCompare with the situation now...
\nJohn Naughton thinks kids should be taught to code in school. Given what is taught at the moment in UK schools for ICT, this isn't a bad idea: Why Kids Should Be Taught Code.
\nDan Rowinski, of ReadWriteWeb, writes about a movement forming in the programming community around the idea of a new standard of literacy: Computer Programming for All: A New Standard of Literacy.
\nMatthew Murray, of ExtremeTech, has a few doubts, and thinks there needs to be more focus on the basics (imagination, logic, reasoning, and problem solving): Should Kids Learn To Code?
\nJeff Atwood (also linked in the RWW article) thinks that you should learn to code for the right reasons, or else focus on more important skills: Please don't learn to code.
", "date_published": "2012-06-01T23:52:52+00:00" } ] }