【问题标题】:What are drawbacks of serializing custom objects along with their definition?序列化自定义对象及其定义的缺点是什么?
【发布时间】:2022-08-10 05:14:28
【问题描述】:

我的问题是,当我在序列化之前通过在__main__ 中“重新声明”它们来“强制”Python 类/函数定义与对象一起序列化时,未来会产生什么影响。

细节

如果定义不在__main__ 中,那么像pickle 和dill 这样的Python 库不会将类或函数定义与对象一起序列化,这是一个常见的问题。

因此,在反序列化对象时,必须在与序列化期间相同的位置找到其依赖项。这增加了部署的一些开销/不灵活性,因为定义必须维护在一个单独的包中,该包必须进行版本控制并存在于(生产)环境中。

我有时会在序列化它们之前使用“维护”对象的解决方法,例如 Oege Dijk here 所述。它本质上是在__main__ 中重新声明对象的定义,以便将其序列化。我使用的代码如下所示。

到目前为止,这种方法在我所有的(机器学习)工作流程中运行良好,已经有一段时间了。然而,它看起来很hacky,我想知道它是否会导致问题,以及哪个。当然,轻松修改序列化定义的能力已被删除(例如错误修复)。但这是我可以忍受的。还有其他我不知道的危险吗?

import inspect
import types

def mainify(obj):
   
    if obj.__module__ != \'__main__\':                                                
        
        import __main__       
        is_func = True if isinstance(obj, types.FunctionType) else False                                                            
                                
        # Get source code and compile
        source = inspect.getsource(obj if is_func else obj.__class__)
        compiled = compile(source, \'<string>\', \'exec\')                    

        # \"Declare\" in __main__ and keep track which key
        # of __main__ dict is new 
        pre = list(__main__.__dict__.keys()) 
        exec(compiled, __main__.__dict__)
        post = list(__main__.__dict__.keys())                        
        new_in_main = list(set(post) - set(pre))[0]
        
        # for function return mainified version, else assign new
        # class to obj and return object
        if is_func:
            obj = __main__.__dict__[new_in_main]            
        else:            
            obj.__class__ = __main__.__dict__[new_in_main]
                
    return obj

    标签: python serialization pickle dill


    【解决方案1】:

    如果您正在从单个模块中提取对象,您可以通过将其分配给变量 dill._dill._main_module 来修改 dill 以欺骗 dill 思考这个模块是__main__ 模块。这是以前版本中的一个选项,但已被删除,所以我现在不知道它是否可以完美运行。 (也许您还需要将module.__name__ 设置为"__main__"None。)

    在下一个dill 版本中,应该在接下来的几天里发布,你将能够通过更新相同的状态来腌制整个模块(或其命名空间的子集)并在不同的会话中加载它模块在那里,如果它已安装,或者将其命名空间加载为字典。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2014-03-03
      相关资源
      最近更新 更多