我是 python 中多处理概念的新手,当我尝试在我的代码中包含多处理时,我在访问变量时遇到了问题。对不起,如果我听起来很天真,但我就是想不通。下面是我的场景的一个简单版本。
class Data:
def __init__(self):
self.data = "data"
def datameth(self):
print self.data
print mainvar
class First:
def __init__(self):
self.first = "first"
def firstmeth(self):
d = Data()
d.datameth()
print self.first
def mymethod():
f = First()
f.firstmeth()
if __name__ == '__main__':
mainvar = "mainvar"
mymethod()
当我运行它时,它运行良好并给出输出:
data
mainvar
first
但是当我尝试将 mymethod() 作为进程运行时
from multiprocessing import Process
class Data:
def __init__(self):
self.data = "data"
def datameth(self):
print self.data
print mainvar
class First:
def __init__(self):
self.first = "first"
def firstmeth(self):
d = Data()
#print mainvar
d.datameth()
print self.first
def mymethod():
f = First()
f.firstmeth()
if __name__ == '__main__':
mainvar = "mainvar"
#mymethod()
p = Process(target = mymethod)
p.start()
我收到这样的错误:
NameError: global name 'mainvar' is not defined
关键是,我无法从 First 类或 Data 类内部访问 mainvar。 我在这里缺少什么?
编辑: 其实在我的真实场景中,它不仅仅是声明mainvar,它是一个方法经过一些处理后的返回值。
if __name__ == '__main__':
***some other stuff***
mainvar = ***return value of some method**
p = Process(target = mymethod)
p.start()
编辑 2: 正如@dciriello 在评论中提到的,它在 Linux 中运行良好,但在 Windows 中运行不正常:(
请您参考如下方法:
这是 Windows 的限制,因为它不支持 fork。在 Linux 中派生子进程时,它会获得父进程状态的写时复制副本,因此您在 if __name__ == "__main__"中定义的 将在那里。但是,在 Windows 上,子进程的状态是通过重新导入程序的 mainvar:__main__ 模块来创建的。这意味着 mainvar 不存在于 child 中,因为它仅在 if __name__ == "__main__" 守卫中创建。因此,如果您需要在子进程中访问 mainvar,您唯一的选择是将其显式传递给子进程作为 Process< 中的 构造函数:mymethod 的参数
mainvar = "whatever"
p = Process(target=mymethod, args=(mainvar,))
此最佳实践在 multiprocessing docs 中有所提及:
Explicitly pass resources to child processes
On Unix a child process can make use of a shared resource created in a parent process using a global resource. However, it is better to pass the object as an argument to the constructor for the child process.
Apart from making the code (potentially) compatible with Windows this also ensures that as long as the child process is still alive the object will not be garbage collected in the parent process.
请注意粗体部分 - 虽然它没有完全清楚地说明,但它有助于 Windows 兼容性的原因是因为它有助于避免您所看到的确切问题。
这也包含在 section of the docs 中专门讨论因缺少 fork 而导致的 Windows 限制:
Global variables
Bear in mind that if code run in a child process tries to access a global variable, then the value it sees (if any) may not be the same as the value in the parent process at the time that
Process.startwas called.However, global variables which are just module level constants cause no problems.
注意“如果有”。因为您的全局变量是在 if __name__ == "__main__": 守卫中声明的,所以它甚至不会出现在 child 中。
