python:使用多处理时访问变量的问题
python: problems with accessing variables while using 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()
当我 运行 这个时,它 运行ning 很好并给出输出:
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
class 或 Data
class 内部访问 mainvar
。
我在这里错过了什么?
编辑:
实际上在我的真实场景中,它不仅仅是声明mainvar,它是经过一些处理后的方法的return值。
if __name__ == '__main__':
***some other stuff***
mainvar = ***return value of some method**
p = Process(target = mymethod)
p.start()
编辑 2:
正如@dciriello 在评论中提到的,它在 Linux 中工作正常,但在 Windows 中工作正常:(
您在错误的地方使用 'mainvar',
试试下面的方法:
from multiprocessing import Process
mainvar = "mainvar"
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()
操作系统不允许进程轻易地共享变量。如果他们愿意,那么每个进程都可以从任何其他进程窃取数据,而你绝不会想要这样(比如当你在网络浏览器中输入你的信用卡详细信息时)。
因此,当您使用 multiprocessing
模块时,您必须使用特殊工具在各个进程(如 Value
和 Array
。 See the documentation 了解详情。
这是 Windows 的限制,因为它不支持 fork
。当 child 进程在 Linux 中分叉时,它会获得 parent 进程状态的 copy-on-write 副本,因此您在 [=] 中定义的 mainvar
13=] 会在那里。但是,在 Windows 上,child 进程的状态是由 re-importing 程序的 __main__
模块创建的。这意味着 mainvar
不存在于 children 中,因为它仅在 if __name__ == "__main__"
守卫内部创建。因此,如果您需要在 child 进程中访问 mainvar
,您唯一的选择是将它显式传递给 child 作为 Process
中 mymethod
的参数=]构造函数:
mainvar = "whatever"
p = Process(target=mymethod, args=(mainvar,))
这个best-practice在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.start
was
called.
However, global variables which are just module level constants cause
no problems.
注意 "if any"。因为您的全局变量是在 if __name__ == "__main__":
守卫内声明的,所以它甚至不会出现在 child.
中
我对 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()
当我 运行 这个时,它 运行ning 很好并给出输出:
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
class 或 Data
class 内部访问 mainvar
。
我在这里错过了什么?
编辑: 实际上在我的真实场景中,它不仅仅是声明mainvar,它是经过一些处理后的方法的return值。
if __name__ == '__main__':
***some other stuff***
mainvar = ***return value of some method**
p = Process(target = mymethod)
p.start()
编辑 2: 正如@dciriello 在评论中提到的,它在 Linux 中工作正常,但在 Windows 中工作正常:(
您在错误的地方使用 'mainvar',
试试下面的方法:
from multiprocessing import Process
mainvar = "mainvar"
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()
操作系统不允许进程轻易地共享变量。如果他们愿意,那么每个进程都可以从任何其他进程窃取数据,而你绝不会想要这样(比如当你在网络浏览器中输入你的信用卡详细信息时)。
因此,当您使用 multiprocessing
模块时,您必须使用特殊工具在各个进程(如 Value
和 Array
。 See the documentation 了解详情。
这是 Windows 的限制,因为它不支持 fork
。当 child 进程在 Linux 中分叉时,它会获得 parent 进程状态的 copy-on-write 副本,因此您在 [=] 中定义的 mainvar
13=] 会在那里。但是,在 Windows 上,child 进程的状态是由 re-importing 程序的 __main__
模块创建的。这意味着 mainvar
不存在于 children 中,因为它仅在 if __name__ == "__main__"
守卫内部创建。因此,如果您需要在 child 进程中访问 mainvar
,您唯一的选择是将它显式传递给 child 作为 Process
中 mymethod
的参数=]构造函数:
mainvar = "whatever"
p = Process(target=mymethod, args=(mainvar,))
这个best-practice在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
:
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.start
was called.However, global variables which are just module level constants cause no problems.
注意 "if any"。因为您的全局变量是在 if __name__ == "__main__":
守卫内声明的,所以它甚至不会出现在 child.