Dee*_*epa 1 python class multiprocessing python-2.7 python-multiprocessing
我是 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()
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它运行良好并给出输出:
data
mainvar
first
Run Code Online (Sandbox Code Playgroud)
但是当我尝试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()
Run Code Online (Sandbox Code Playgroud)
我收到这样的错误:
NameError: global name 'mainvar' is not defined
Run Code Online (Sandbox Code Playgroud)
关键是,我无法mainvar从First班级或Data班级内部访问。我在这里缺少什么?
编辑:实际上在我的真实场景中,它不仅仅是声明 mainvar,它是经过一些处理的方法的返回值。
if __name__ == '__main__':
***some other stuff***
mainvar = ***return value of some method**
p = Process(target = mymethod)
p.start()
Run Code Online (Sandbox Code Playgroud)
编辑 2:正如@dciriello 在评论中提到的,它在 Linux 中运行良好,但在 Windows 中却没有:(
这是 Windows 的限制,因为它不支持fork. 当一个子进程在 Linux 中被 fork 时,它会得到一个父进程状态的写时复制副本,所以mainvar你在里面定义的if __name__ == "__main__":将在那里。但是,在 Windows 上,子进程的状态是通过重新导入__main__程序模块来创建的。这意味着mainvar在孩子中不存在,因为它只在if __name__ == "__main__"守卫内部创建。因此,如果您需要mainvar在子进程内部进行访问,您唯一的选择是mymethod在Process构造函数中将其作为参数显式传递给子进程:
mainvar = "whatever"
p = Process(target=mymethod, args=(mainvar,))
Run Code Online (Sandbox Code Playgroud)
multiprocessing文档中提到了这种最佳实践:
显式地将资源传递给子进程
在 Unix 上,子进程可以使用在使用全局资源的父进程中创建的共享资源。但是,最好将对象作为参数传递给子进程的构造函数。
除了使代码(可能)与 Windows 兼容之外,这还确保只要子进程仍然存在,对象就不会在父进程中被垃圾收集。
请注意粗体部分 - 虽然它没有完全说明,但它有助于 Windows 兼容性的原因是因为它有助于避免您看到的确切问题。
这也包含在文档的部分中,该部分专门讨论了由于缺少以下内容而导致的 Windows 限制fork:
全局变量
请记住,如果在子进程中运行的代码尝试访问全局变量,那么它看到的值(如果有)可能与
Process.start调用时父进程中的值不同。然而,只是模块级常量的全局变量不会引起任何问题。
注意“如果有”。因为您的全局变量是在if __name__ == "__main__":警卫内部声明的,所以它甚至不会出现在孩子中。
| 归档时间: |
|
| 查看次数: |
1040 次 |
| 最近记录: |