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,它只会丢失对配置模块中对象的引用。

即使不这样做,如果变量的更改发生在各个模块的导入时,也很难跟踪实际的导入顺序。

当您添加线程时,由于各种竞争条件,这将变得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并用global_var = 7重新分配它,这只会改变当前模块上下文中local_var名称所指向的位置。config.local_var仍然引用原始值。

既然您已经了解了它,那么值得一看队列模块以及线程本地对象

当它仍然不起作用时

另一种看不到更改的可能性是,由于并行性不在您的代码中,而是在另一个库中,它正在用multiprocessing模块而不是线程生成进程。

如果你期望线程和多处理派生进程,你会遇到的问题正是你所描述的:全局变量的更改在其他进程中不可见(当然,这只是因为每个进程都有自己的变量)。

如果是这样的话,就有可能拥有(数字的、类型化的)跨进程同步的对象。检查ArrayValue类,以及多处理Queue,以便能够发送和接收(大部分)任意对象。

(请在代码中添加一行import multiprocessing; print(multiprocessing.current_process())。与结果无关,请建议RandomizedSearchCV文档的维护人员明确提及他们为并行性所做的工作)

相关内容

  • 没有找到相关文章

最新更新