Python多处理PicklingError:Can';t pickle<;类型';功能'&燃气轮机;
很抱歉,我不能用一个简单的例子重现这个错误,我的代码太复杂了,无法发布。如果我用ipythonshell而不是普通的Python来运行这个程序,事情就会进展顺利 我查阅了以前关于这个问题的一些笔记。它们都是由使用池调用类函数中定义的函数引起的。但我不是这样 线程thread-3中的异常: 回溯(最近一次呼叫最后一次): 文件“/usr/lib64/python2.7/threading.py”,第552行,在引导程序内部 self.run() 文件“/usr/lib64/python2.7/threading.py”,第505行,正在运行 自我目标(*自我参数,**自我参数) 文件“/usr/lib64/python2.7/multiprocessing/pool.py”,第313行,在任务处理中 放置(任务) PicklingError:无法pickle:属性查找\内置\函数失败 我将感谢任何帮助 更新:函数I pickle在模块的顶层定义。尽管它调用了一个包含嵌套函数的函数。i、 e,Python多处理PicklingError:Can';t pickle<;类型';功能'&燃气轮机;,python,multiprocessing,pickle,python-multiprocessing,Python,Multiprocessing,Pickle,Python Multiprocessing,很抱歉,我不能用一个简单的例子重现这个错误,我的代码太复杂了,无法发布。如果我用ipythonshell而不是普通的Python来运行这个程序,事情就会进展顺利 我查阅了以前关于这个问题的一些笔记。它们都是由使用池调用类函数中定义的函数引起的。但我不是这样 线程thread-3中的异常: 回溯(最近一次呼叫最后一次): 文件“/usr/lib64/python2.7/threading.py”,第552行,在引导程序内部 self.run() 文件“/usr/lib64/python2.7/th
f()
调用g()
调用h()
,它有一个嵌套函数i()
,我正在调用池。应用异步(f)
f()
,g()
,h()
都是在顶层定义的。我用这个模式尝试了一个更简单的例子,但效果很好。下面是一个例子。特别是,如果函数是在模块的顶层定义的,那么它们才是可拾取的
这段代码:
import multiprocessing as mp
class Foo():
@staticmethod
def work(self):
pass
if __name__ == '__main__':
pool = mp.Pool()
foo = Foo()
pool.apply_async(foo.work)
pool.close()
pool.join()
产生与您发布的错误几乎相同的错误:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 315, in _handle_tasks
put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
请注意,
foo
是可拾取的,因为foo
是在顶层定义的,foo.\uuu dict\uuuu
是可拾取的。我发现,通过尝试在完美工作的代码段上使用探查器,我也可以准确地生成错误输出
请注意,这是在Windows上进行的(在Windows上,分叉稍微不那么优雅)
我在跑步:
python -m profile -o output.pstats <script>
python-m profile-o output.pstats
并发现删除配置文件会删除错误,而放置配置文件会恢复错误。因为我知道以前的代码是可以工作的,所以我也快疯了。我正在检查pool.py是否有更新。。。然后有一种下沉的感觉,消除了轮廓,就是这样
在这里发布存档,以防其他人遇到。我会使用
pathos.multiprocessing
,而不是multiprocessing
<代码>病态。多处理是多处理
的一个分支,它使用dill
dill
可以序列化python中的几乎所有内容,因此您可以并行发送更多内容。pathos
fork还可以直接处理多个参数函数,这是类方法所需要的
>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> p = Pool(4)
>>> class Test(object):
... def plus(self, x, y):
... return x+y
...
>>> t = Test()
>>> p.map(t.plus, x, y)
[4, 6, 8, 10]
>>>
>>> class Foo(object):
... @staticmethod
... def work(self, x):
... return x+1
...
>>> f = Foo()
>>> p.apipe(f.work, f, 100)
<processing.pool.ApplyResult object at 0x10504f8d0>
>>> res = _
>>> res.get()
101
>>来自pathos.multiprocessing导入ProcessingPool作为池
>>>p=池(4)
>>>类别测试(对象):
... def plus(自身、x、y):
... 返回x+y
...
>>>t=测试()
>>>p.map(t.plus,x,y)
[4, 6, 8, 10]
>>>
>>>类Foo(对象):
... @静力学方法
... def工作(自我,x):
... 返回x+1
...
>>>f=Foo()
>>>p.apipe(f.work,f,100)
>>>res=_
>>>res.get()
101
在这里获取pathos
(如果您愿意,dill
):
正如其他人所说的那样,
多处理
只能将Python对象传输到可以进行pickle处理的工作进程。如果您不能按照unutbu的描述重新组织代码,您可以使用dill的扩展酸洗/反酸洗功能来传输数据(尤其是代码数据),如下所示
此解决方案只需要安装dill
,而不需要安装其他库,如pathos
:
import os
from multiprocessing import Pool
import dill
def run_dill_encoded(payload):
fun, args = dill.loads(payload)
return fun(*args)
def apply_async(pool, fun, args):
payload = dill.dumps((fun, args))
return pool.apply_async(run_dill_encoded, (payload,))
if __name__ == "__main__":
pool = Pool(processes=5)
# asyn execution of lambda
jobs = []
for i in range(10):
job = apply_async(pool, lambda a, b: (a, b, a * b), (i, i + 1))
jobs.append(job)
for job in jobs:
print job.get()
print
# async execution of static method
class O(object):
@staticmethod
def calc():
return os.getpid()
jobs = []
for i in range(10):
job = apply_async(pool, O.calc, ())
jobs.append(job)
for job in jobs:
print job.get()
这个解决方案只需要安装dill,而不需要安装其他库
def apply_packeted_function_for_map((转储的_function、item、args、kwargs)):
"""
将转储函数解包为目标函数,并使用参数调用它。
:param(函数、项、参数、kwargs):
转储函数及其参数的元组
:返回:
目标函数的结果
"""
目标函数=卸载(卸载函数)
res=目标函数(项目,*args,**kwargs)
返回res
def打包功能用于打包映射(目标打包功能、项目、*args、**kwargs):
"""
将函数和参数打包到可以从一个
多处理。处理到另一个。主要问题是:
«多处理.Pool.map*»或«应用*»
不能使用类方法或闭包。
它用«dill»解决了这个问题。
它使用目标函数作为参数,转储它(«with dill»)
并返回带有目标函数参数的转储函数。
为了获得更高的性能,我们只转储目标函数本身
不要放弃它的论点。
如何使用(伪代码):
~>>>导入多处理
~>>>图像=[…]
~>>>pool=multiprocessing.pool(100500)
~>>>features=pool.map(
~…*打包功能\u用于\u映射(
~…超级(提取器,自身)。提取功能,
~…图像,
~…type='png'
~.**选择,
~... )
~... )
~>>>
:参数目标函数:
函数,您希望像target_函数一样执行它(item,*args,**kwargs)。
:参数项:
地图项目列表
:param args:
目标函数的位置参数(项、*args、**kwargs)
:param kwargs:
目标函数的命名参数(项,*args,**kwargs)
:return:tuple(函数包装、转储项)
它返回一个元组
*函数包装器,解包并调用目标函数;
*压缩目标函数及其参数的列表。
"""
转储函数=转储(目标函数)
dumped_items=[(dumped_函数、item、args、,
import os
from multiprocessing import Pool
import dill
def run_dill_encoded(payload):
fun, args = dill.loads(payload)
return fun(*args)
def apply_async(pool, fun, args):
payload = dill.dumps((fun, args))
return pool.apply_async(run_dill_encoded, (payload,))
if __name__ == "__main__":
pool = Pool(processes=5)
# asyn execution of lambda
jobs = []
for i in range(10):
job = apply_async(pool, lambda a, b: (a, b, a * b), (i, i + 1))
jobs.append(job)
for job in jobs:
print job.get()
print
# async execution of static method
class O(object):
@staticmethod
def calc():
return os.getpid()
jobs = []
for i in range(10):
job = apply_async(pool, O.calc, ())
jobs.append(job)
for job in jobs:
print job.get()
Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
import dill
import itertools
def run_dill_encoded(payload):
fun, args = dill.loads(payload)
res = fun(*args)
res = dill.dumps(res)
return res
def dill_map_async(pool, fun, args_list,
as_tuple=True,
**kw):
if as_tuple:
args_list = ((x,) for x in args_list)
it = itertools.izip(
itertools.cycle([fun]),
args_list)
it = itertools.imap(dill.dumps, it)
return pool.map_async(run_dill_encoded, it, **kw)
if __name__ == '__main__':
import multiprocessing as mp
import sys,os
p = mp.Pool(4)
res = dill_map_async(p, lambda x:[sys.stdout.write('%s\n'%os.getpid()),x][-1],
[lambda x:x+1]*10,)
res = res.get(timeout=100)
res = map(dill.loads,res)
print(res)
from multiprocessing.pool import ThreadPool as Pool