Python 中的 ProcessPoolExecutor 和 Lock
Posted
技术标签:
【中文标题】Python 中的 ProcessPoolExecutor 和 Lock【英文标题】:ProcessPoolExecutor and Lock in Python 【发布时间】:2016-05-25 11:28:30 【问题描述】:我正在尝试将 concurrent.futures.ProcessPoolExecutor
与 Locks 一起使用,但我遇到了运行时错误。
(如果相关,我正在使用 Windows)
这是我的代码:
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
import time
def f(i, lock):
with lock:
print(i, 'hello')
time.sleep(1)
print(i, 'world')
def main():
lock = multiprocessing.Lock()
pool = ProcessPoolExecutor()
futures = [pool.submit(f, num, lock) for num in range(3)]
for future in futures:
future.result()
if __name__ == '__main__':
main()
这是我得到的错误:
Traceback (most recent call last):
File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\queues.py", line 242, in _feed
obj = ForkingPickler.dumps(obj)
File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\reduction.py", line 50, in dumps
cls(buf, protocol).dump(obj)
File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\synchronize.py", line 102, in __getstate__
context.assert_spawning(self)
File "F:\WinPython-64bit-3.4.3.2\python-3.4.3.amd64\Lib\multiprocessing\context.py", line 347, in assert_spawning
' through inheritance' % type(obj).__name__
RuntimeError: Lock objects should only be shared between processes through inheritance
奇怪的是,如果我用multiprocessing.Process
编写相同的代码,一切正常:
import multiprocessing
import time
def f(i, lock):
with lock:
print(i, 'hello')
time.sleep(1)
print(i, 'world')
def main():
lock = multiprocessing.Lock()
processes = [multiprocessing.Process(target=f, args=(i, lock)) for i in range(3)]
for process in processes:
process.start()
for process in processes:
process.join()
if __name__ == '__main__':
main()
这行得通,我得到:
1 hello
1 world
0 hello
0 world
2 hello
2 world
【问题讨论】:
【参考方案1】:您需要使用Manager
并改用Manager.Lock()
:
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
import time
def f(i, lock):
with lock:
print(i, 'hello')
time.sleep(1)
print(i, 'world')
def main():
pool = ProcessPoolExecutor()
m = multiprocessing.Manager()
lock = m.Lock()
futures = [pool.submit(f, num, lock) for num in range(3)]
for future in futures:
future.result()
if __name__ == '__main__':
main()
结果:
% python locks.py
0 hello
0 world
1 hello
1 world
2 hello
2 world
【讨论】:
最好用Manager.Lock()
解释为什么可以解决问题。
这是因为Manager.Lock()
可以腌制而multiprocessing.Lock()
不能腌制。【参考方案2】:
我试验了它按预期工作的代码。 我的理解是 Manager.Lock() 返回要获取的句柄(即 multiprocessing.managers.AcquirerProxy)。当它与关键字“with”一起使用时,它实际上锁定了除当前处理器之外的所有处理器,以便“with”范围内的代码片段充当单个处理。
【讨论】:
以上是关于Python 中的 ProcessPoolExecutor 和 Lock的主要内容,如果未能解决你的问题,请参考以下文章