1

谁能告诉我为什么我的代码和函数序列化处理程序在下面不起作用?该copyreg模块对我来说相当陌生,不清楚下面的代码是否正确编写。

>>> import pickle, copyreg, types, marshal
>>> def average(*args):
    return sum(args) / len(args)

>>> average_dump = pickle.dumps(average)
>>> del average
>>> average = pickle.loads(average_dump)
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    average = pickle.loads(average_dump)
AttributeError: 'module' object has no attribute 'average'
>>> copyreg.pickle(types.CodeType,
           lambda code: (marshal.loads, (marshal.dumps(code),)),
           marshal.loads)
>>> up = lambda co, ns, de, cl: types.FunctionType(co, globals(), na, de, cl)
>>> copyreg.pickle(types.FunctionType,
           lambda function: (up, (function.__code__,
                      function.__name__,
                      function.__defaults__,
                      function.__closure__)),
           up)
>>> def average(*args):
    return sum(args) / len(args)

>>> average_dump
b'\x80\x03c__main__\naverage\nq\x00.'
>>> pickle.dumps(average)
b'\x80\x03c__main__\naverage\nq\x00.'
>>> del average; average = pickle.loads(average_dump)
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    del average; average = pickle.loads(average_dump)
AttributeError: 'module' object has no attribute 'average'

我的期望是,如果注册的函数正常工作,那么代码和函数对象都会被序列化。如果按预期工作,解酸功能也是可能的。


编辑:按照此答案Pickler中的建议进行子类化。似乎也没有帮助。示例中的函数仍按名称而不是模块中的处理程序进行序列化。copyreg

>>> import pickle, copyreg, types, marshal
>>> copyreg.pickle(types.CodeType,
           lambda code: (marshal.loads, (marshal.dumps(code),)),
           marshal.loads)
>>> up = lambda co, ns, de, cl: types.FunctionType(co, globals(), na, de, cl)
>>> copyreg.pickle(types.FunctionType,
           lambda function: (up, (function.__code__,
                      function.__name__,
                      function.__defaults__,
                      function.__closure__)),
           up)
>>> class MyPickler(pickle.Pickler):
    def __init__(self, *args):
        super().__init__(*args)
        self.dispatch_table = copyreg.dispatch_table


>>> def average(*args):
    return sum(args) / len(args)

>>> x = io.BytesIO(); y = MyPickler(x)
>>> y.dump(average)
>>> x.getvalue()
b'\x80\x03c__main__\naverage\nq\x00.'
4

2 回答 2

0

如果要序列化函数,请运行以下命令:

pip install dill

完成后,您可以import dill使用它来代替pickle模块。

如果您正在运行 Python 3 并希望轻松访问pip,请将批处理文件放在名为的 Windows 目录中pip.bat,并将以下行放入其中(假设您有一个干扰 SSL 的代理):

py -3 -m pip %* --trusted-host pypi.org --trusted-host files.pythonhosted.org
于 2019-04-18T20:31:46.237 回答
-2

函数不能按值腌制:

请注意,函数(内置的和用户定义的)是通过“完全限定”名称引用而不是值来腌制的。这意味着只有函数名和定义函数的模块的名称被腌制。函数的代码和它的任何函数属性都没有被腌制。因此,定义模块必须在 unpickling 环境中是可导入的,并且模块必须包含命名对象,否则将引发异常。

http://docs.python.org/2/library/pickle.html#what-c​​an -be-pickled-and-unpickled )

于 2013-06-11T15:12:10.463 回答