酸洗包裹的部分功能 [英] Pickling wrapped partial functions

查看:114
本文介绍了酸洗包裹的部分功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用部分函数创建可腌制的装饰器.但是,尝试这样做时,我总是收到腌制错误.

I am trying to create a picklable decorator using partial functions. However, I keep getting pickling errors when trying to do that.

第一个朴素的示例如下:

The first naïve example is as follows:

def decorator(func):
  def wrapper(**kwargs):
    return partial(func, **kwargs)
  return wrapper

@decorator
def decorated(x, y=1, z=2):
  return x+y+z

y5 = decorated(y=5)
pickle.dumps(y5)

functools提取partial的地方.

少一些幼稚的尝试涉及在def wrapper上方添加@wraps一行.这没有帮助.

A bit less naïve attempt involves adding @wraps one line above def wrapper. This doesn't help.

我不确定我了解酸洗的原理.

I'm not sure I understand how pickling really works.

推荐答案

问题出在您的装饰器中,而不是 partial .一个 partial 对象应该腌制得很好:

The problem is in your decorator, not with partial. A partial object should pickle just fine:

>>> from pickle import *
>>> from functools import *
>>> f = partial(pow, 2)
>>> p = dumps(f)
>>> g = loads(p)
>>> g(5)
32

因此,您的代码存在的问题在装饰器中.它不保留原始功能的名称.尝试以下方法:

So, this issue with your code is in the decorator. It is not preserving the name of the original function. Try this instead:

import pickle
from functools import *

def decorator(func):
    def wrapper(**kwargs):
        return partial(func, **kwargs)
    return wrapper

def decorated(x, y=1, z=2):
    return x+y+z

dd = decorator(decorated)

y5 = dd(y=5)
pickle.dumps(y5)

使用dd的修改应允许pickle逻辑按其名称发现底层函数.这就是泡菜的工作方式.

The modification to use dd should allow the pickle logic to discover the underlying function by its name. That is how pickles work.

要查看泡菜中的函数名称,请查看转储输出:

To see the function name in the pickle, look at the dumps output:

>>> print pickle.dumps(y5)
cfunctools
partial
p0
(c__main__
decorated
p1
tp2
Rp3
(g1
(t(dp4
S'y'
p5
I5
sNtp6
b.

装饰"一词必须是可找到的,等于基础功能,并且不被装饰器隐藏.请记住,当函数被腌制时,只会存储它们的名称.函数的实际内容不在泡菜中.

The word "decorated" needs to be findable, equal to the underlying function, and not be hidden by the decorator. Remember, when functions get pickled, only their names get stored. The actual contents of the function aren't in the pickle.

有一些解决方法,但是它们不是很漂亮.您可以使用 __ setstate __()来保存函数名称及其源代码.然后添加一个 __ getstate __()方法,通过执行其源代码来还原该函数.

There are some workarounds, but they aren't pretty. You can use __setstate__() to save both the function name and its source-code. Then add a __getstate__() method to restore the function by exec-ing its source.

或者,您可以在函数对象对象中提取字节码并将其保存.恢复后,编译代码对象并执行.

Alternatively, you can extract the byte codes in the function object object and save those. Upon a restore, compile the code object and exec it.

简而言之,使用带有@表示法的装饰器的目标与函数酸洗的工作原理直接矛盾.为了实现您的目标,您必须自定义函数酸洗以使其保存函数的功能,而不仅仅是其名称.

In short, your goal of using a decorator with the @ notation is directly at odds with how function pickling works. In order to achieve your goal, you'll have to customize function pickling to have it save what the function does, not just its name.

这篇关于酸洗包裹的部分功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆