我在多处理过程中遇到了一种奇怪的行为。
当我尝试在从多处理调用的函数中使用全局变量时,它看不到全局变量。
示例:
import multiprocessing
def func(useless_variable):
print(variable)
useless_list = [1,2,3,4,5,6]
p = multiprocessing.Pool(processes=multiprocessing.cpu_count())
variable = "asd"
func(useless_list)
for x in p.imap_unordered(func, useless_list):
pass
输出:
asd
multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "/usr/lib/python3.4/multiprocessing/pool.py", line 119, in worker
result = (True, func(*args, **kwds))
File "pywork/asd.py", line 4, in func
print(variable)
NameError: name 'variable' is not defined
"""
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "pywork/asd.py", line 11, in <module>
for x in p.imap_unordered(func, useless_list):
File "/usr/lib/python3.4/multiprocessing/pool.py", line 689, in next
raise value
NameError: name 'variable' is not defined
如您所见,我第一次只是致电func
,就会按预期打印asd
。然而,当我使用多处理调用相同的函数时,它表示变量variable
不存在,即使在我之前清楚地打印它之后也是如此。
多处理是否忽略全局变量?我该如何解决这个问题?
答案 0 :(得分:1)
当您向某个进程发送垃圾邮件时,所有上下文都会被复制,您需要使用managers
来替换它们之间的对象,检查official documentations,以便管理状态检查this。
答案 1 :(得分:1)
multiprocessing
时, Pool
Pool
分叉(或以某种方式产生用于模仿Windows分叉的方式)其工作进程。 fork
将父内存映射为子代中的写时复制,但它不会在它们之间创建持久的联系;在fork
之后,父项中所做的更改在子项中不可见,反之亦然。您不能使用在创建Pool
之后定义的任何变量,并且在创建Pool
之前对变量所做的更改将不会反映在worker中。
通常,使用Pool
,您希望完全避免可变的全局状态;将所有需要的数据传递给函数imap
- 作为参数(或其他)作为参数(序列化并发送给子节点,因此状态正确),并具有函数{{1}任何新数据而不是变换全局变量,它将序列化并将其发送回父进程以便在其认为合适时使用。
return
是一个选项,但通常不是Managers
s的正确选项;你通常想要坚持只创建Pool
之前只读全局变量的工人,或者使用参数并返回新值,而不是使用全局状态。