我想在“a.py”中定义一个函数,它使用多处理进行并行化,然后将其作为库函数导入“b.py”。例如,在“a.py”中:
import multiprocessing as mp, queue
def MPWorker(input, i):
input.put(i)
def MPTest(MaxMPNum):
jobs = []
BatchResult = queue.Queue()
for i in range(MaxMPNum):
p = mp.Process(target=MPWorker, args=(BatchResult, i + 1))
p.start()
print("this is", i)
jobs.append(p)
for i in range(MaxMPNum):
print("getting", i)
result = BatchResult.get()
print(result)
然后在“b.py”中:
import a
a.MPTest(10)
但是,它不起作用,我总是会收到错误:_pickle.PicklingError:无法pickle:_thread上的属性查找锁失败。 那么,是否有可能以这种方式使用python的多处理,或者我错过了什么?
整个回溯,略有编辑(Python 3.x,Windows):
Traceback (most recent call last):
File "F:/b.py", line 72, in <module>
a.MPTest(5)
File "F:\a.py", line 566, in MPTest
p.start()
File "C:\Python34\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "C:\Python34\lib\multiprocessing\context.py", line 212, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Python34\lib\multiprocessing\context.py", line 313, in _Popen
return Popen(process_obj)
File "C:\Python34\lib\multiprocessing\popen_spawn_win32.py", line 66, in __init__
reduction.dump(process_obj, to_child)
File "C:\Python34\lib\multiprocessing\reduction.py", line 59, in dump
ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class '_thread.lock'>: attribute lookup lock on _thread failed
答案 0 :(得分:5)
问题是你正在使用queue.Queue
,它只能在同一进程中的线程之间工作,而不是在进程之间工作的multiprocessing.Queue
。
根据您的平台以及您使用它的方式,这将以不同的方式失败。在你的情况下,因为你试图将队列作为参数传递给Process
构造函数,并且你在Windows上,你得到了最好的错误:你试图挑选队列本身,那就失败了。 *在Unix上,您实际上可以成功地将队列传递给子进程,但是当您使用它时,它可能会丢失大部分值(OS X)或死锁(大多数其他系统)。
正如the docs解释的那样,multiprocessing.Queue
“是queue.Queue
”的近似克隆,除了它是“线程和进程安全”而不仅仅是线程安全。
如果您认为 使用multiprocessing.Queue
,那么您的错误就在于此行:
import multiprocessing as mp, queue
这不导入multiprocessing
和mp
queue
,导入multiprocessing
mp
,导入queue
本身。有关详细信息,请参阅import
上的参考资料。
这对人类来说是模棱两可的(尽管它对解析器来说并不模糊)是Python中不鼓励使用多重导入语句的原因之一。例如,PEP 8表示“导入通常应该在不同的行上”。
*如果队列本身在你腌制它时引发异常,而不是依赖于它使用一些不可打击的线程同步对象的事实,那可能会更好,因为挑选{{1}并不是很明显}是由于挑选_thread.lock
。