multiprocessing_generator 模块触发权限错误
Posted
技术标签:
【中文标题】multiprocessing_generator 模块触发权限错误【英文标题】:multiprocessing_generator modules triggers a permission error 【发布时间】:2019-05-27 21:49:53 【问题描述】:我找到了模块multiprocessing_generator。 我使用以下代码尝试了该模块:
from multiprocessing_generator import ParallelGenerator
def my_generator():
yield (x*x for x in range(200))
with ParallelGenerator(my_generator(), max_lookahead=100) as g:
for elem in g:
print(elem)
这是我得到的错误(我在控制台中运行了我的代码,python 文件在我的桌面中):
C:\Users\crd\Desktop>python test.py Traceback(最近一次调用最后): 文件“test.py”,第 69 行,在 使用 ParallelGenerator(my_generator(), max_lookahead=100) 作为 g: 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\site-packages\multiprocessing_generator__init__.py", 第 62 行,在 输入 self.process.start() 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\process.py", 第 112 行,开始 self._popen = self._Popen(self) 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\context.py", 第 223 行,在 _Popen 返回 _default_context.get_context().Process._Popen(process_obj) 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\context.py", 第 322 行,在 _Popen 返回 Popen(process_obj) 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\popen_spawn_win32.py", 第 65 行,在 init 中 reduction.dump(process_obj, to_child) 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\reduction.py", 第 60 行,在转储中 ForkingPickler(file, protocol).dump(obj) AttributeError: Can't pickle local object 'ParallelGenerator.init..wrapped'
C:\Users\crd\Desktop>Traceback(最近一次调用最后):文件 "",第 1 行,在文件中 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\spawn.py", 第 99 行,在 spawn_main new_handle = reduction.steal_handle(parent_pid, pipe_handle) 文件 "C:\Users\crd\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\reduction.py", 第 87 行,在steal_handle 中 _winapi.DUPLICATE_SAME_ACCESS | _winapi.DUPLICATE_CLOSE_SOURCE) PermissionError: [WinError 5] Accès refusé
我清理了 multiprocessing_generator 模块中的代码(我删除了每个 try/exeption,我将上下文管理器转换为基本函数)。但是使用下面的代码我得到了同样的错误:
from queue import Empty
from multiprocessing import Process, Queue
def ParallelGeneratorLight():
queue = Queue()
def wrapped():
for item in (x*x for x in range(200)):
queue.put(item)
process = Process(target=wrapped)
process.start()
queue.get()
print(ParallelGeneratorLight())
这有什么问题?
【问题讨论】:
【参考方案1】:multiprocessing_generator
依赖于使用'fork'
启动方法的多处理模块,因为它假定wrapped
嵌套函数(在ParallelGenerator
的__init__
中定义)可以作为target
传递multiprocessing.Process
对象。在基于fork
ing 的平台上,这很好;子进程继承父进程的完整状态(除了线程等一些小例外),因此它可以平等地访问wrapped
嵌套函数(毕竟它继承了一个精确的副本)。
问题是,在 Windows 上,唯一可用的启动方法是 'spawn'
,它要求 target
(和所有参数)为 pickle
able(pickle
s 它们,将它们发送给孩子IPC,并在那里重建它们),并且嵌套函数永远不会pickle
able(pickle
ing 函数涉及将其限定名称酸洗以在另一侧导入和使用,并且嵌套函数的限定名称涉及不可导入的组件,在这种情况下,pickle
ing ParallelGenerator.__init__.<locals>.wrapped
失败,因为 <locals>
显然不是可导入的名称)。
基本上,multiprocessing_generator
仅适用于类 UNIX 系统,并且仅当您使用默认启动方法时 ('fork'
);如果您 called set_start_method
具有其他值('forkserver'
或 'spawn'
),则无法使 multiprocessing_generator
工作。
虽然这是一个错误,但在大多数情况下它并不是一个特别严重的错误;如果生成器必须对其值进行腌制,则该模块几乎没有什么好处,因为大多数此类生成器本身不是pickle
able(例如大多数类似文件的对象)或pickle
ing它们涉及运行它们以完成(在这种情况下,你就失去了所有的并行性)。
抱歉,这里的简单回答是:不要在 Windows 上使用 multiprocessing_generator
。
也就是说,如果您的生成器是 I/O 绑定的,您可能可以通过导入模块从模块中受益,然后立即对其进行猴子修补以替换它的所有 multiprocessing
组件依赖于它们等效的multiprocessing.dummy
名称(由线程支持,并且不依赖于酸洗),例如
from multiprocessing_generator import ParallelGenerator
import multiprocessing.dummy, multiprocessing_generator
# Monkey-patch to use threads
multiprocessing_generator.Process = multiprocessing.dummy.Process
multiprocessing_generator.Queue = multiprocessing.dummy.Queue
需要明确的是,我没有测试过这个;没有任何明示或暗示的保证,这是否会起作用。如果生成器受 CPU 限制,至少在 CPython 参考解释器上,这也是完全没有意义的,因为受 CPU 限制的生成器在运行时将持有the GIL,从而阻止主线程执行工作,因此您不妨进行迭代直接。
【讨论】:
以上是关于multiprocessing_generator 模块触发权限错误的主要内容,如果未能解决你的问题,请参考以下文章