4

Below are two python programs. They're exactly the same, except for one is split into two functions. However only the one that's split into two functions doesn't work - the second function doesn't work. Why would this be?

Note the code is taken from this useful blog post.

Without functions (works):

import gtk

def show_window_function(x, y):
    print x
    print y

# get the indicate module, which does all the work
import indicate

# Create a server item
mm = indicate.indicate_server_ref_default()
# If someone clicks your server item in the MM, fire the server-display signal
mm.connect("server-display", show_window_function)
# Set the type of messages that your item uses. It's not at all clear which types
# you're allowed to use, here.
mm.set_type("message.im")
# You must specify a .desktop file: this is where the MM gets the name of your
# app from.
mm.set_desktop_file("/usr/share/applications/nautilus.desktop")
# Show the item in the MM.
mm.show()

# Create a source item
mm_source = indicate.Indicator()
# Again, it's not clear which subtypes you are allowed to use here.
mm_source.set_property("subtype", "im")
# "Sender" is the text that appears in the source item in the MM
mm_source.set_property("sender", "Unread")
# If someone clicks this source item in the MM, fire the user-display signal
mm_source.connect("user-display", show_window_function)
# Light up the messaging menu so that people know something has changed
mm_source.set_property("draw-attention", "true")
# Set the count of messages in this source.
mm_source.set_property("count", "15")
# If you prefer, you can set the time of the last message from this source,
# rather than the count. (You can't set both.) This means that instead of a
# message count, the MM will show "2m" or similar for the time since this
# message arrived.
# mm_source.set_property_time("time", time.time())
mm_source.show()

gtk.mainloop()

With functions (second function is executed but doesn't actually work):

import gtk

def show_window_function(x, y):
    print x
    print y

# get the indicate module, which does all the work
import indicate

def function1():
    # Create a server item
    mm = indicate.indicate_server_ref_default()
    # If someone clicks your server item in the MM, fire the server-display signal
    mm.connect("server-display", show_window_function)
    # Set the type of messages that your item uses. It's not at all clear which types
    # you're allowed to use, here.
    mm.set_type("message.im")
    # You must specify a .desktop file: this is where the MM gets the name of your
    # app from.
    mm.set_desktop_file("/usr/share/applications/nautilus.desktop")
    # Show the item in the MM.
    mm.show()

def function2():
    # Create a source item
    mm_source = indicate.Indicator()
    # Again, it's not clear which subtypes you are allowed to use here.
    mm_source.set_property("subtype", "im")
    # "Sender" is the text that appears in the source item in the MM
    mm_source.set_property("sender", "Unread")
    # If someone clicks this source item in the MM, fire the user-display signal
    mm_source.connect("user-display", show_window_function)
    # Light up the messaging menu so that people know something has changed
    mm_source.set_property("draw-attention", "true")
    # Set the count of messages in this source.
    mm_source.set_property("count", "15")
    # If you prefer, you can set the time of the last message from this source,
    # rather than the count. (You can't set both.) This means that instead of a
    # message count, the MM will show "2m" or similar for the time since this
    # message arrived.
    # mm_source.set_property_time("time", time.time())
    mm_source.show()

function1()
function2()
gtk.mainloop()

1 Answer 1

2

mm_source is local to function2. When function2 completes it goes out of scope and is garbage collected. This causes it to be quickly added and then removed from the menu before you can see it.

To stop this from happening, simply return the mm_source object to the calling code, and keep it around in a variable. You probably will want to do the same thing with your mm too. As follows:


import gtk

def show_window_function(x, y):
    print x
    print y

# get the indicate module, which does all the work
import indicate

def function1():
    # Create a server item
    mm = indicate.indicate_server_ref_default()
    # If someone clicks your server item in the MM, fire the server-display signal
    mm.connect("server-display", show_window_function)
    # Set the type of messages that your item uses. It's not at all clear which types
    # you're allowed to use, here.
    mm.set_type("message.im")
    # You must specify a .desktop file: this is where the MM gets the name of your
    # app from.
    mm.set_desktop_file("/usr/share/applications/nautilus.desktop")
    # Show the item in the MM.
    mm.show()
    return mm

def function2():
    # Create a source item
    mm_source = indicate.Indicator()
    # Again, it's not clear which subtypes you are allowed to use here.
    mm_source.set_property("subtype", "im")
    # "Sender" is the text that appears in the source item in the MM
    mm_source.set_property("sender", "Unread")
    # If someone clicks this source item in the MM, fire the user-display signal
    mm_source.connect("user-display", show_window_function)
    # Light up the messaging menu so that people know something has changed
    mm_source.set_property("draw-attention", "true")
    # Set the count of messages in this source.
    mm_source.set_property("count", "15")
    # If you prefer, you can set the time of the last message from this source,
    # rather than the count. (You can't set both.) This means that instead of a
    # message count, the MM will show "2m" or similar for the time since this
    # message arrived.
    # mm_source.set_property_time("time", time.time())
    mm_source.show()
    return mm_source

my_mm = function1()
my_mm_source = function2()
gtk.mainloop()

2
  • I think you're absolutely right. Might moving to an OOP approach make this easier?
    – 8128
    Mar 15, 2011 at 20:01
  • Sure. It would certainly be a more structured way to bundle up the objects than just using random global variables. You would still have to do the same thing, but inside the scope of your class instead of with globals. Mar 15, 2011 at 20:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .