python threading with global variables
i encountered a problem when write python threading code, that i wrote some workers threading classes, they all import a global file like sharevar.py, i need a variable like regdevid to keep tracking the register device id, then when one thread change it's value, then other threads can get it fresh, but the result is that: when one thread change it's value, the others still get the default value i defined in sharevar.py file, why? anything wrong with me?
# thread a
from UserShare import RegDevID
import threading
class AddPosClass(threadin开发者_C百科g.Thread):
global commands
# We need a pubic sock, list to store the request
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
data = self.queue.get()
#print data
RegDevID = data
#print data
send_queue.put(data)
self.queue.task_done()
# thread b
import threading
from ShareVar import send_queue, RegDevID
"""
AddPos -- add pos info on the tail of the reply
"""
class GetPosClass(threading.Thread):
global commands
# We need a pubic sock, list to store the request
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
data = self.queue.get()
#print data
data = RegDevID
#print data
send_queue.put(data)
self.queue.task_done()
# ShareVar.py
RegDevID = '100'
That's it, when thread a changed the RegDevID, thread b still get it's default value. Thanks advanced.
from ShareVar import RegDevID
class Test():
def __init__(self):
pass
def SetVar(self):
RegDevID = 999
def GetVar(self):
print RegDevID
if __name__ == '__main__':
test = Test();
test.SetVar()
test.GetVar()
The ShareVar.py:
RegDevID = 100
The result:
100
why?
My guess is you are trying to access the shared variable without a lock
. If you do not acquire a lock and attempt to read a shared variable in one thread, while another thread is writing to it, the value could be indeterminate.
To remedy, make sure you acquire a lock in the thread before reading or writing to it.
import threading
# shared lock: define outside threading class
lock = threading.RLock()
# inside threading classes...
# write with lock
with lock: #(python 2.5+)
shared_var += 1
# or read with lock
with lock:
print shared_var
Read about Python threading.
Answer to your bottom problem with scoping:
In your bottom sample, you are experiencing a problem with scoping. In SetVar()
, you are create a label RegDevID
local to the function. In GetVar()
, you are attempting to read from a label RegDevID
but it is not defined. So, it looks higher in scope and finds one defined in the import. The variables need to be in the same scope if you hope to have them reference the same data.
Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
the innermost scope, which is searched first, contains the local names the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names the next-to-last scope contains the current module’s global names the outermost scope (searched last) is the namespace containing built-in names
If a name is declared global, then all references and assignments go directly to the middle scope containing the module’s global names. Otherwise, all variables found outside of the innermost scope are read-only (an attempt to write to such a variable will simply create a new local variable in the innermost scope, leaving the identically named outer variable unchanged).
Read about scoping.
Are you sure you posted your actual code? You imported RegDevID from two different modules:
# thread a
from UserShare import RegDevID
vs
# thread b
from ShareVar import send_queue, RegDevID
Either way, your problam has nothing to do with threading. Think of 'from somemodule import somevar' as an assignment statement. Roughly equivalent to some magic to load the module if it isn't already loaded followed by:
somevar = sys.modules['somemodule'].somevar
When you import RegDevID from the other module you are creating a fresh name in the current module. If you mutate the object then other users of the object will see the changes, but if you rebind the name in this module then that only affects the local name it doesn't change anything in the original module.
Instead you need to rebind the variable in another module:
import ShareVar
...
ShareVar.RegDevID = data
Except of course you'll find you get on much better if you create a class to manage your shared state.
Your second bit of code is ejust misunderstanding local and global variables:
def SetVar(self):
RegDevID = 999
inside the function you created a new local variable RegDevID which is nothing to do with the global variable of the same name. Use the global
statement if you want to rebind a global variable:
def SetVar(self):
global RegDevID
RegDevID = 999
精彩评论