繁体   English   中英

保存在 function 中定义的 class

[英]Saving a class defined inside a function

我的代码目前的结构如下。

script1.py中,我有以下内容:

def func():
    class MyClass():
        pass
    return MyClass

script2.py中,我有以下内容:

import script1
import pickle

the_class = script1.func()

f = open(FILE_PATH, "wb")
pickle.dump(the_class, f)
f.close()

但是, script2.py给出了一个错误:

AttributeError: Can't pickle local object 'func.<locals>.MyClass'

问题 1:为什么会发生这种情况? 我怎样才能解决这个问题?

问题 #2:我可以重组代码以更简洁的方式实现相同的结果吗? 我希望我的 class 的定义出现在一个单独的模块中。 一旦我将 class “引入”到我的主脚本中,我想保存它。

谢谢!

回答问题 1:这是因为每次调用 function 时,都会创建一个新的 class。 所以 class 在模块级别是未知的。 据我所知,这是泡菜的要求。 而且我没有办法解决这个问题。

要解决第二个问题,最好知道您为什么要这样做。 你想解决什么问题? 这可能有助于指导解决方案。

我是dill作者。 我不知道你为什么说dill帮不了你。 首先,如果我们尝试序列化您的 class,它会起作用:

>>> def func():
...   class MyClass():
...     pass
...   return MyClass
... 
>>> import dill
>>> c = func()
>>> c
<class '__main__.func.<locals>.MyClass'>
>>> 
>>> dill.dumps(c)
b'\x80\x03cdill._dill\n_create_type\nq\x00(cdill._dill\n_load_type\nq\x01X\x04\x00\x00\x00typeq\x02\x85q\x03Rq\x04X\x07\x00\x00\x00MyClassq\x05h\x01X\x06\x00\x00\x00objectq\x06\x85q\x07Rq\x08\x85q\t}q\n(X\n\x00\x00\x00__module__q\x0bX\x08\x00\x00\x00__main__q\x0cX\x07\x00\x00\x00__doc__q\rNutq\x0eRq\x0f.'
>>> c_ = dill.loads(_)
>>> c_
<class '__main__.MyClass'>
>>> 

所以,既然我们知道 class 是序列化的,那么我们可以从您的模块中获取它......虽然这是事情......如果您尝试序列化未安装的模块中定义的任何内容(即仅从您导入的脚本从当前目录),那么它应该由于序列化程序无法找到本地定义的模块而失败(除非它在__main__中)。 问题在于模块...如果您因任何原因反对安装模块...那么您必须求助于dill的一个鲜为人知的功能,即从 object 获取源代码。 如下所示,您可以获取 class 并在本地定义它,或者您可以获取 function 并在本地定义它。 然后它会序列化:

>>> import dill
>>> import script1
>>> exec(dill.source.getsource(script1.func(), lstrip=True))
>>> MyClass
<class '__main__.MyClass'>
>>> # or...
>>> exec(dill.source.getsource(script1.func))
>>> c = func()
>>> 
>>> dill.dumps(c)
b'\x80\x03cdill._dill\n_create_type\nq\x00(cdill._dill\n_load_type\nq\x01X\x04\x00\x00\x00typeq\x02\x85q\x03Rq\x04X\x07\x00\x00\x00MyClassq\x05h\x01X\x06\x00\x00\x00objectq\x06\x85q\x07Rq\x08\x85q\t}q\n(X\n\x00\x00\x00__module__q\x0bX\x08\x00\x00\x00__main__q\x0cX\x07\x00\x00\x00__doc__q\rNutq\x0eRq\x0f.'
>>> dill.loads(_)
<class '__main__.MyClass'>
>>> 

要做的事情是不要尝试从未安装的模块序列化。 安装您将从中导入的模块,或者将生成 class 的 function 放在与转储 class 的脚本相同的文件中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM