[英]Global variables accross modules and threads in python
我有一个配置文件config.py,其中包含一个全局变量,即在config.py中,我有(默认值为5)
# config.py
globalVar = 5
现在在模块run.py中,设置全局变量,然后调用打印函数:
# run.py
import config
import test
config.globalVar = 7
test.do_printing()
# test.py
import config
def do_printing():
print(config.globalVar)
这很好用(即打印了7),但是如果我使用多个线程进行打印(在test.py中),它将不再起作用,即线程看不到run.py所做的更改(即打印了5)。
如何解决呢?
即使在同一线程上运行,您在执行该操作时也可能会遇到问题。 例如,如果您是from config import globalVar
,那么,如果您在本地模块中重新绑定globalVar,它只会失去对config模块中对象的引用。
即使您不这样做,如果在各个模块的导入时对变量进行了更改,也很难跟踪实际的导入顺序。
当添加线程时,由于各种竞争条件,这将变得100%无法管理。 除了竞争条件(即,您的一个线程在另一个线程上设置变量之前先读取该变量)或错误导入之外,线程不应以您描述的方式影响全局变量更改的可见性。
具有确定性代码的解决方案是使用适合于跨线程交换(以及跨线程数据保护)的数据结构。
threading
模块本身提供了Event
对象,您可以使用该对象来确保一个线程等待,直到另一个线程更改了您期望的值:
config.py:
changed = Event()
changed.clear()
global_var = 5
工作线程中的模块:
import config
def do_things():
while True:
config.changed.wait() # blocks until other thread sets the event
do_more_things_with(config.global_var)
在主线程上:
import config
config.global_var = 7
config.changed.set() # FRees the waiting Thread to run
请注意,在上面的代码中,我总是用点分符号引用config中的对象。 这对于“事件”对象没有什么区别-我可以from config import changed
来做-因为我正在处理同一个对象的内部状态,所以它可以工作-但是如果我from config import global_var
做from config import global_var
并用global_var = 7
重新分配,仅更改当前模块上下文中local_var
名称的位置。 config.local_var
仍引用原始值。
无法看到更改的另一种可能性是,由于并行性不在您的代码中,而是在另一个库中,因此它使用multiprocessing
模块而不是线程来生成进程。
如果您期望线程并且拥有多进程生成的进程,那么您遇到的问题将正是您所描述的:全局变量的更改在其他变量中不可见(当然,这是因为每个进程都有自己的变量)。
在这种情况下,有可能具有跨进程同步的(数字,类型化的)对象。 检查Array
和Value
类,以及multiprocessing Queue
,使其能够发送和接收(主要是)任意对象。
(确保在您的代码中添加一个import multiprocessing; print(multiprocessing.current_process())
行。请确保不依赖于结果,建议RandomizedSearchCV文档的维护者明确提及他们为并行性所做的工作)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.