在 python 中将自定义模块与对象一起序列化

gsm*_*fra 8 python serialization python-module pickle dill

问题

假设我有这个模块名为custom_module

class CustomClass:
    pass
Run Code Online (Sandbox Code Playgroud)

我在脚本中使用此类来序列化我在以下位置定义的类的对象custom_module

import cloudpickle
import custom_module as cm

custom_object = cm.CustomClass()
with open('filename.pkl', 'wb') as file:
    cloudpickle.dump(custom_object, file)
Run Code Online (Sandbox Code Playgroud)

我将此 pickle 文件复制到另一个环境并使用另一个脚本加载它:

import cloudpickle

with open('filename.pkl', 'rb') as file:
    custom_object = cloudpickle.load(file)
Run Code Online (Sandbox Code Playgroud)

这会产生这个错误:

Traceback (most recent call last):
  File "loader.py", line 4, in <module>
    custom_object = cloudpickle.load(file)
ModuleNotFoundError: No module named 'custom_module'
Run Code Online (Sandbox Code Playgroud)

尴尬的解决方案

作为解决方法,可以读取并执行custom_module脚本中的所有内容:

exec(open(path.join('custom_module.py')).read())
Run Code Online (Sandbox Code Playgroud)

但这看起来真的很奇怪,我不能使用 CustomClass 作为cm.CustomClass. 是否有其他解决方案不涉及将第一个环境中的所有代码复制到第二个环境中?

lin*_*k89 1

CustomClass您可以通过custom_module以下方式重新实现来解决该问题:

def __CustomClass():
    class CustomeClass:
        ... # Your implementaion here
    return CustomeClass

CustomClass = __CustomClass()
Run Code Online (Sandbox Code Playgroud)

如果你足够幸运的话,错误就会消失。如果没有,您需要深入CustomClass查找其他本地模块中定义的其他函数或类,并使用相同的方法重新实现它们。

您可以在这个问题中找到更多详细信息。您也可以使用它cloudpickle.register_pickle_by_value来解决该问题,但它被标记为实验性功能。