"But it doesn't mean anything"

08 Feb, 2014

Jeremy Paxman talking with a conservative activist on the "Year of Code" (at about 9 minutes in) announces: "But it doesn't mean anything".

By 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...

(Oh yeah... and the artistic looking garbage on your big screen really doesn't mean anything ツ)


Tcl/Tk warning message when starting IDLE

31 Dec, 2013

Stan W writes (NB. edited for brevity):

Over the last couple of days I have started using your great book with my two sons (13 and 15 years old). I'm reaching out to you with the following question because I have noticed other people asking about the same issue online, with at least one mentioning your book, so I think you posting the question and answer to your blog might help other people in addition to me and my sons.

We are using Mac OSX and have installed Python 3.3.3 from python.org, and are getting this message when opening IDLE:

"WARNING: The version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk/ for current information."

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 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), but IDLE keeps showing the same error message.

Thank you very much for any help you can provide!

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.

Hope that helps.


Left and right, or top and bottom

14 Dec, 2013

Matthias writes:

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 learning more by reading your book. I like your book.

I think on page 202 is a little mistake. You wrote:

"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:"

Shouldn't it be "left or right sides of the canvas" instead?

Hi Matthias. You're doing well to have gotten as far as you have, at 7 years of age. Well done!

You're absolutely right about the mistake, and I've updated the errata accordingly. Thanks very much for the "bug report". ツ


Problem with the turtle module

30 Oct, 2013

Mark F writes:

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. In Chapter 8, Classes and Objects, you reintroduce the turtle module. You say that we can create 'an object of the pen class,' which makes sense.

import turtle
avery = turtle.pen()
kate = turtle.pen()

However, when I attempt to move the turtle using either one of those objects, I get this error:

avery.forward(50)
Traceback (most recent call last):
   File "\<pyshell#3>", line 1, in
     avery.forward(50)
AttributeError: '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 but have tried with 3.2 and encounter the same error. Please let me know why I keep getting this error so that I can keep moving forward.

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? In 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
>>> turtle.pen
<function pen at 0x10117fe60>
>>> turtle.Pen
<class turtle.Turtle>

Without 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
avery = turtle.Pen()
kate = turtle.Pen()

...you should have a bit more success.


Loop confusion

26 Sep, 2013

Justin B writes:

I recently started the section on "For Loops" and am somewhat confused about something. The section (page 55) runs a loop for "HugeHairyPants." I setup the loop as you indicated and actually understood the result just fine.

However, I decided to add a variable in the mix and went one step further. Here is my script:

hugehairypants = ['huge', 'hairy', 'pants'] for i in hugehairypants:     print(i)     for j in hugehairypants:         print(j)         for k in hugehairypants:             print(k)

This loop doesn't seem to follow the same progression of the other loop or maybe I just don't understand it correctly. I figured it would print a variable from i and then j and then print the full loop of items in k, but it doesn't seem to do that. If you have a moment, could explain how this loop would work?

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:

hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    print(i)
    for j in hugehairypants:    # LOOP 2
        print(j)
        for k in hugehairypants:    # LOOP 3
            print(k)

And the output:

huge   (LOOP 1, first time)
    huge   (LOOP 2, first time)
        huge   (LOOP 3, first time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, first time)
        huge   (LOOP 3, second time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, first time)
        huge   (LOOP 3, third time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
hairy  (LOOP 1, first time)
    huge   (LOOP 2, second time)
        huge   (LOOP 3, fourth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, second time)
        huge   (LOOP 3, fifth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, second time)
        huge   (LOOP 3, sixth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
pants  (LOOP 1, first time)
    huge  (LOOP 2, third time)
        huge   (LOOP 3, seventh time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, third time)
        huge   (LOOP 3, eighth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, third time)
        huge   (LOOP 3, ninth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)

So loop 1 outputs the list once, loop 2 outputs the list three times, and loop 3 outputs the list nine times in total.

As a side note, we could have also altered the code to do the indentation for us:

hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    print(i)
    for j in hugehairypants:    # LOOP 2
        print('    %s' % j)
        for k in hugehairypants:    # LOOP 3
            print('        %s' % k)

And, 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:

time_label = ['','first','second','third','fourth','fifth','sixth','seventh','eighth','ninth']
i_counter = 0
j_counter = 0
k_counter = 0
hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    if i == 'huge':
        i_counter += 1
    print('%s (LOOP 1, %s time)' % (i, time_label[i_counter]))
    for j in hugehairypants:    # LOOP 2
        if j == 'huge':
            j_counter += 1
        print('    %s (LOOP 2, %s time)' % (j, time_label[j_counter]))
        for k in hugehairypants:    # LOOP 3
            if k == 'huge':
                k_counter += 1
            print('        %s (LOOP 3, %s time)' % (k, time_label[k_counter]))

Python installation confusion on Mac OS X

19 Sep, 2013

Justin J writes:

I installed python 3.3.2 for my macbook running version 10.6.8 and typed this in, open -a "/Applications/Python 3.2/IDLE.app" --args -n and it didn't work:

"The action Run 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.

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. 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 which python mentioned something about ActiveTcl 8.5. It recommended I download 32, so I got rid of 64/32 and re-downloaded 32 bit and it finally gave me no error in the shell.

I thought I'd ask if this was an ok thing for me to do?

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.

ActiveState have a dmg installation file, so once you've downloaded it, double-click on the file, and a dialog will appear:

ActiveTcl installation dialog

You 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.

Apart from that, your change to the open command is correct, so once ActiveTcl is installed, you should be good to go.


What is -n for

27 Aug, 2013

John writes:

Quick question regarding the -n used in the shortcut for IDLE. I realize that it starts IDLE with no subprocesses, but what does that mean and why do we want to do it?

There's precious little on the net describing what the -n switch does. From the IDLE documentation:

If IDLE is started with the -n command line switch it will run in a single process and will not create the subprocess which runs the RPC Python execution server. This can be useful if Python cannot create the subprocess or the RPC socket interface on your platform. However, in this mode user code is not isolated from IDLE itself. Also, the environment is not restarted when Run/Run Module (F5) is selected. If your code has been modified, you must reload() the affected modules and re-import any specific items (e.g. from foo import baz) if the changes are to take effect. For these reasons, it is preferable to run IDLE with the default subprocess if at all possible.

Which, I admit, doesn't help a huge amount...

For 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.


Tkinter problems on the Raspberry Pi

09 Jul, 2013

Ben writes:

I am 12 and I am reading your book, Python for Kids. I have recently confronted a problem with the module tkinter. I have recently got a rasberry pi to program on python. I am pretty sure that tkinter is already installed on python, but when I run something like:

def hello():     print('hello there') from tkinter import * tk = Tk() btn = Button(tk, text='click me', command=hello) btn.pack()

There is nothing that pops up! I am frustrated and need help! Please help, me and my father are new to linux by the way and don't know what to do.

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:

###
>>> from tkinter import *
>>> tk = Tk()
>>> canvas = Canvas(tk, width=400, height=400)
>>> canvas.pack()
>>> canvas.create_arc(10, 10, 200, 80, extent=45, style=ARC)
>>> canvas.create_arc(10, 80, 200, 160, extent=90, style=ARC)
>>> canvas.create_arc(10, 160, 200, 240, extent=135, style=ARC)
>>> canvas.create_arc(10, 240, 200, 320, extent=180, style=ARC)
>>> canvas.create_arc(10, 320, 200, 400, extent=359, style=ARC)###
>>> tk.mainloop()

Python Kinderleicht

30 Jun, 2013

Python Kinderleicht cover This arrived in the mail from No Starch today.

Sehr cool!

The 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).


On Feedly

28 Jun, 2013

Rather 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.

feedly error screen 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.

feedly loading screen 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.

feedly flick 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.

So, 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.

Still... better than Reader nothing...

Update: turns out that Reeder coupled with Feedly in the backend (for the moment) is the ideal solution.