如何在函数中使用多处理?

时间:2014-10-29 01:10:25

标签: python python-3.x multiprocessing

我想在“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

1 个答案:

答案 0 :(得分:5)

问题是你正在使用queue.Queue,它只能在同一进程中的线程之间工作,而不是在进程之间工作的multiprocessing.Queue

根据您的平台以及您使用它的方式,这将以不同的方式失败。在你的情况下,因为你试图将队列作为参数传递给Process构造函数,并且你在Windows上,你得到了最好的错误:你试图挑选队列本身,那就失败了。 *在Unix上,您实际上可以成功地将队列传递给子进程,但是当您使用它时,它可能会丢失大部分值(OS X)或死锁(大多数其他系统)。

正如the docs解释的那样,multiprocessing.Queue“是queue.Queue”的近似克隆,除了它是“线程和进程安全”而不仅仅是线程安全。


如果您认为 使用multiprocessing.Queue,那么您的错误就在于此行:

import multiprocessing as mp, queue

这不导入multiprocessingmp queue,导入multiprocessing mp,导入queue本身。有关详细信息,请参阅import上的参考资料。

这对人类来说是模棱两可的(尽管它对解析器来说并不模糊)是Python中不鼓励使用多重导入语句的原因之一。例如,PEP 8表示“导入通常应该在不同的行上”。


*如果队列本身在你腌制它时引发异常,而不是依赖于它使用一些不可打击的线程同步对象的事实,那可能会更好,因为挑选{{1}并不是很明显}是由于挑选_thread.lock

造成的