How to get gobject.idle_add() to pass a parameter by reference?
I have two threads in my Py开发者_StackOverflow社区GTK app:
- the main thread which runs the GTK loop and does all the GUI stuff
- another thread which handles network requests, etc.
I need to have the second thread get some information from the first thread, so I call:
variable = None
gobject.idle_add( function_in_main_thread, variable )
In the main thread I have:
def function_in_main_thread( variable ):
variable = 1
The problem is that the variable in the second thread never gets set. It's value remains at None
. So how can I get the main thread to actually modify the variable in the other thread?
Note: I have some thread synchronization code in the script in case anyone is concerned about modifying variables in other threads. I omitted it from this example because I felt it really didn't apply to the real issue.
In Python, assignment always creates the name in the current scope. The name you pass is indeed a reference to the variable you've created, but the assignment operator will try to find it in the current scope and, if it's not there, create it.
>>> def assign_to(name, value):
... name = value
...
>>> name = "nothing"
>>> assign_to(name, 5)
>>> name
'nothing'
You can instead pass a reference to some kind of instance, a type or maybe even a list, and then use some method of that instance.
>>> def append_to_list(my_list, value):
... my_list.append(value)
...
>>> my_list = []
>>> append_to_list(my_list, 5)
>>> my_list
[5]
The list could of course equally be just an empty object with a "value" member.
In short, if you want to do something akin to call by reference, avoid the assignment operator. Use some kind of method of the object instead.
There's a neat, and surprisingly terse guide to Python Namespaces by Shrutarshi Basu, in case you want to dig deeper. In order to understand what the assignment operator is doing, check out wp: Name Binding. It also explains why the assignment operator can't be overloaded in Python.
Also, as you pointed out, you need to call gobject.threads_init()
精彩评论