具有多处理功能的Python装饰器失败
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了具有多处理功能的Python装饰器失败,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2950字,纯文字阅读大概需要5分钟。
内容图文
![具有多处理功能的Python装饰器失败](/upload/InfoBanner/zyjiaocheng/698/0bebb13ba95d4575b9262b1f9071518f.jpg)
我想在函数上使用一个装饰器,我将随后传递给一个多处理池.但是,代码失败了“PicklingError:无法pickle:属性查找__builtin __.函数失败”.我不太明白为什么它在这里失败了.我确信它很简单,但我找不到它.下面是一个最小的“工作”示例.我认为使用functools函数就足以让它工作了.
如果我注释掉功能装饰,它的工作没有问题.我在这里误解多处理是什么意思?有没有办法让这项工作?
编辑:添加可调用的类装饰器和函数装饰器之后,事实证明函数装饰器按预期工作.可调用类装饰器继续失败.什么是可调用的类版本,使其不被腌制?
import random
import multiprocessing
import functools
class my_decorator_class(object):
def __init__(self, target):
self.target = target
try:
functools.update_wrapper(self, target)
except:
pass
def __call__(self, elements):
f = []
for element in elements:
f.append(self.target([element])[0])
return f
def my_decorator_function(target):
@functools.wraps(target)
def inner(elements):
f = []
for element in elements:
f.append(target([element])[0])
return f
return inner
@my_decorator_function
def my_func(elements):
f = []
for element in elements:
f.append(sum(element))
return f
if __name__ == '__main__':
elements = [[random.randint(0, 9) for _ in range(5)] for _ in range(10)]
pool = multiprocessing.Pool(processes=4)
results = [pool.apply_async(my_func, ([e],)) for e in elements]
pool.close()
f = [r.get()[0] for r in results]
print(f)
解决方法:
问题是,泡菜需要有一些方法来重新组装你所腌制的所有东西.请点击此处查看可以腌制的清单:
http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled
在picking my_func时,需要对以下组件进行pickle:
> my_decorator_class的一个实例,名为my_func
这可以. Pickle将存储类的名称并腌制其__dict__内容. unpickling时,它使用名称来查找类,然后创建一个实例并填写__dict__内容.但是,__ dict__内容存在问题……
>存储在my_func.target中的原始my_func的实例
这不太好.它是顶层的功能,通常可以腌制. Pickle将存储该函数的名称.然而,问题是名称“my_func”不再绑定到未修饰的函数,它绑定到修饰函数.这意味着pickle将无法查找未修饰的函数来重新创建对象.可悲的是,pickle没有办法知道它试图腌制的对象总是可以在名称main.my_func下找到.
您可以像这样更改它,它将工作:
import random
import multiprocessing
import functools
class my_decorator(object):
def __init__(self, target):
self.target = target
try:
functools.update_wrapper(self, target)
except:
pass
def __call__(self, candidates, args):
f = []
for candidate in candidates:
f.append(self.target([candidate], args)[0])
return f
def old_my_func(candidates, args):
f = []
for c in candidates:
f.append(sum(c))
return f
my_func = my_decorator(old_my_func)
if __name__ == '__main__':
candidates = [[random.randint(0, 9) for _ in range(5)] for _ in range(10)]
pool = multiprocessing.Pool(processes=4)
results = [pool.apply_async(my_func, ([c], {})) for c in candidates]
pool.close()
f = [r.get()[0] for r in results]
print(f)
您已经观察到,当类没有时,装饰器功能会起作用.我相信这是因为functools.wraps修改了修饰函数,以便它具有它包装的函数的名称和其他属性.就pickle模块而言,它与普通的顶级函数无法区分,因此它通过存储其名称来腌制它.在unpickling,名称绑定到装饰功能,所以一切都工作.
内容总结
以上是互联网集市为您收集整理的具有多处理功能的Python装饰器失败全部内容,希望文章能够帮你解决具有多处理功能的Python装饰器失败所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。