[Tutor] command in menu and button

John Fouhy john at fouhy.net
Tue Nov 22 23:00:27 CET 2005


Apologies to Double Six for getting this twice; I forgot to cc: tutor..

On 23/11/05, Double Six <doublesix at ureach.com> wrote:
> menu.add_command(label="Open Viewer", command=os.system("Open my
> viewer &"))

Hi Joe,

This is a fairly common gotcha.

Think about what happens when python executes a function call:
Firstly, it evaluates each of the arguments to the function.  Then, it
calls the function.

So, with your line above, here's what python does:

 1. Evaluate "Open Viewer".  This is easy; it just produces a string.
 2. Evaluate os.system("Open my viewer &").  Since this is a function
call, in order to evaluate it, python calls the function to get its
return value.
 3. Call menu.add_command with the arguments it has just evaluated.

Do you see what is happening now?  What python wants is a _callable_
--- this is like a function that hasn't been called yet.

Functions are first-class objects in python.  That means you can do
things like this:

>>> def hello():
...  print 'hello world!'
...
>>> hello()
hello world!
>>> f = hello          # assign to f the function hello.
>>> f()                # f is now a function, so we can call it.
hello world!

Or, I could make a quit button like this:

b = Button(self, text='Quit program', command=self.quit)
# assuming 'self' is a Frame or Tk or something.

Note the lack of () after self.quit: We're passing a reference to the
method itself.

So, to your specific problem:

menu.add_command(label="Open Viewer", command=os.system("Open my viewer &"))

It's a bit more difficult, because you want to pass an argument to
os.system.  And when Tkinter calls a menu callback, it doesn't give it
any arguments.

But, that's OK.  You can just define a new function:

def callback():
 os.system("Open my viewer &")
menu.add_command(label="Open Viewer", command=callback)

Does this help?

--
John.


More information about the Tutor mailing list