# thread a
from UserShare import RegDevID
import threading
class AddPosClass(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
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'
就是这样,当线程a更改了RegDevID时,线程b仍然获得它的默认值。 谢谢高级。
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()
ShareVar.py:
RegDevID = 100
结果:
100
为什么?
答案 0 :(得分:6)
我的猜测是你试图在没有lock
的情况下访问共享变量。如果您没有获取锁并尝试在一个线程中读取共享变量,而另一个线程正在写入该值,则该值可能是不确定的。
要解决此问题,请确保在读取或写入之前获取线程中的锁定。
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
通过范围界定回答您的底层问题:
在您的底部示例中,您遇到了范围问题。在SetVar()
中,您将在函数的本地创建标签RegDevID
。在GetVar()
中,您试图从标签RegDevID
中读取,但未定义。因此,它在范围上看起来更高,并在导入中找到一个定义的。如果您希望变量引用相同的数据,则变量需要在同一范围内。
尽管范围是静态确定的,但它们是动态使用的。 在执行期间的任何时候,那里 至少有三个嵌套的范围 命名空间可以直接访问:
首先搜索的最里面的范围包含本地名称 任何封闭函数的范围,从搜索开始 最近的封闭范围, 包含非本地,但也包括 非全球名称 倒数第二个范围包含当前模块的全局名称 最外面的范围(最后搜索)是包含的命名空间 内置名称
如果名称被声明为全局,则全部 参考和作业直接进行 到包含的中间范围 模块的全局名称。否则,全部 在外面发现的变量 最里面的范围是只读的(一个 试图写入这样的变量 将简单地创建一个新的本地 最里面的变量, 留下同名的外层 变量不变)。
答案 1 :(得分:3)
您确定发布了实际代码吗?您从两个不同的模块导入了RegDevID:
# thread a
from UserShare import RegDevID
VS
# thread b
from ShareVar import send_queue, RegDevID
无论哪种方式,你的problam都与线程无关。将'from somemodule import somevar'视为赋值语句。如果模块尚未加载,则大致相当于加载模块的一些魔法,然后是:
somevar = sys.modules['somemodule'].somevar
从其他模块导入RegDevID时,您将在当前模块中创建一个新名称。如果你改变对象,那么该对象的其他用户将看到更改,但是如果你重新绑定该模块中的名称,那么它只会影响本地名称,它不会改变原始模块中的任何内容。
相反,您需要在另一个模块中重新绑定变量:
import ShareVar
...
ShareVar.RegDevID = data
除非你创建一个类来管理你的共享状态,否则你会发现你会更好。
你的第二点代码是对局部和全局变量的误解:
def SetVar(self):
RegDevID = 999
在函数内部创建了一个新的局部变量RegDevID,它与同名的全局变量无关。如果要重新绑定全局变量,请使用global
语句:
def SetVar(self):
global RegDevID
RegDevID = 999