多处理没有看到全局变量?

时间:2016-08-23 08:01:11

标签: python-3.x multiprocessing global

我在多处理过程中遇到了一种奇怪的行为。

当我尝试在从多处理调用的函数中使用全局变量时,它看不到全局变量。

示例:

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不存在,即使在我之前清楚地打印它之后也是如此。

多处理是否忽略全局变量?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

当您向某个进程发送垃圾邮件时,所有上下文都会被复制,您需要使用managers来替换它们之间的对象,检查official documentations,以便管理状态检查this

答案 1 :(得分:1)

在创建multiprocessing时,

Pool Pool分叉(或以某种方式产生用于模仿Windows分叉的方式)其工作进程。 fork将父内存映射为子代中的写时复制,但它不会在它们之间创建持久的联系;在fork之后,父项中所做的更改在子项中不可见,反之亦然。您不能使用在创建Pool之后定义的任何变量,并且在创建Pool之前对变量所做的更改将不会反映在worker中。

通常,使用Pool,您希望完全避免可变的全局状态;将所有需要的数据传递给函数imap - 作为参数(或其他)作为参数(序列化并发送给子节点,因此状态正确),并具有函数{{1}任何新数据而不是变换全局变量,它将序列化并将其发送回父进程以便在其认为合适时使用。

return是一个选项,但通常不是Managers s的正确选项;你通常想要坚持只创建Pool之前只读全局变量的工人,或者使用参数并返回新值,而不是使用全局状态。