Python 为什么酸洗多处理串行化取决于范围?

Python 为什么酸洗多处理串行化取决于范围?,python,python-3.x,serialization,multiprocessing,pickle,Python,Python 3.x,Serialization,Multiprocessing,Pickle,我试图理解并发在一般情况下是如何工作的,在本例中,它在Python中是如何工作的 我使用inputs库已经有一段时间了,并且在使用它生成进程时总是不得不“作弊”——使用subprocess.Popen执行脚本。今天,我不用花太多心思,就将一行代码放在了另一个地方,并成功地生成了一个以函数为目标的进程。但我不明白为什么它会起作用 下面的代码公开了两个简单的类,一个在self中保存对控制器的引用,另一个不保存(并使用模块中声明的全局引用): 导入输入 导入多处理 导入时间 控制器=输入。设备。游戏板

我试图理解并发在一般情况下是如何工作的,在本例中,它在Python中是如何工作的

我使用
inputs
库已经有一段时间了,并且在使用它生成进程时总是不得不“作弊”——使用
subprocess.Popen执行脚本。今天,我不用花太多心思,就将一行代码放在了另一个地方,并成功地生成了一个以函数为目标的
进程。但我不明白为什么它会起作用

下面的代码公开了两个简单的类,一个在self中保存对
控制器的引用,另一个不保存(并使用模块中声明的全局引用):

导入输入
导入多处理
导入时间
控制器=输入。设备。游戏板[0]
类testbreak:
定义初始化(自):
self.controller=控制器
def读取(自):
尽管如此:
ev=self.controller.read()[0]
打印(车辆代码、车辆状态)
类测试工作:
def读取(自):
尽管如此:
ev=控制器。读取()[0]
打印(车辆代码、车辆状态)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
t=TestWorking()
#取消注释下面的行以获取错误
#t=testbreaked()
multiprocessing.Process(target=t.read).start()
尽管如此:
打印(“我还活着!”)
时间。睡眠(1)
取消注释
#t=testbreak()
后的错误如下:

回溯(最近一次呼叫最后一次):
文件“C:/Coding/…”,第31行,在
multiprocessing.Process(target=t.read).start()
文件“C:\Python\lib\multiprocessing\process.py”,第121行,在开始处
self.\u popen=self.\u popen(self)
文件“C:\Python\lib\multiprocessing\context.py”,第224行,在\u Popen中
返回_default_context.get_context().Process._Popen(Process_obj)
文件“C:\Python\lib\multiprocessing\context.py”,第326行,在\u Popen中
返回Popen(过程对象)
文件“C:\Python\lib\multiprocessing\popen\u spawn\u win32.py”,第93行,在\uuuu init中__
减少.转储(进程对象,到子进程)
文件“C:\Python\lib\multiprocessing\reduce.py”,第60行,转储文件
ForkingPickler(文件、协议).dump(obj)
AttributeError:无法pickle本地对象“CDLL.\uu init\uu..\u FuncPtr”

我不太明白存储对对象的引用是如何让
pickle
变得疯狂的,而在模块级存储相同的引用是允许的。我恳请您帮助揭开这个问题背后的秘密。

当一个进程启动多进程时,父进程的全局变量将复制到创建的所有子进程中。因此,父进程中的任何更改不应反映在子进程的副本上。TestBreak类中的代码部分有一个构造函数,它将类变量分配给全局变量,然后尝试读取它。而TestWorking类只是创建了一个局部变量ev来读取控制器(在全局范围内)。

这根本没有描述酸洗问题,也没有说明这种情况会起作用的原因。您可以轻松地将全局控制器实例替换为某个自定义类,而不是
输入
类,并成功地对其进行pickle。
TestBroker
TestWorking
都可以正常工作。此外,父进程甚至无法更改任何内容,因为如上所述,由于酸洗错误,它无法创建任何内容。