来自导入类的对象的 cloudpickle 与在发生酸洗的同一模块中定义的类

mor*_*fys 4 python pickle cloudpickle

我注意到,由 cloudpickle.dump(obj) 生成的 pickle 文件会有所不同,具体取决于 obj 的类(称为 SubClass,BaseClass 的子类)是否在与 cloudpickling 发生的模块相同的模块中导入或定义。

特别是,如果导入 BaseClass 和 SubClass,则 pickle 文件仅存储对 MyClass 模块和类的引用,这是通过反汇编字节码确定的。

如果 BaseClass 和 SubClass 定义在与 cloudpickling 发生的同一模块中,则 pickle 文件似乎存储 BaseClass 和 SubClass 的代码。

有谁知道为什么会发生这种情况?这是因为当对象在主模块中定义时,cloudpickle 会完全序列化对象及其类吗?

BaseClass 和 SubClass 定义在与 cloudpickling 发生相同的模块中:

import cloudpickle
import pickletools


class BaseClass:
    def func(self):
        print("BaseClass")


class SubClass(BaseClass):
    def subfunc(self):
        print("SubClass")


obj = SubClass()
with open("cloudpickle_object.pkl", "wb") as f:
    cloudpickle.dump(obj, f)

with open("cloudpickle_object.pkl", "rb") as infile:
    pickletools.dis(infile)
Run Code Online (Sandbox Code Playgroud)

反汇编器的输出显示 pickle 文件中的 BaseClass 和 SubClass 代码:

   83: \x8c     SHORT_BINUNICODE 'SubClass'
   93: \x94     MEMOIZE    (as 6)
   94: h        BINGET     2
   96: (        MARK
   97: h            BINGET     5
   99: \x8c         SHORT_BINUNICODE 'BaseClass'
  110: \x94         MEMOIZE    (as 7)
  111: h            BINGET     3
  113: \x8c         SHORT_BINUNICODE 'object
Run Code Online (Sandbox Code Playgroud)

从发生 cloudpickling 的不同模块导入的基类和子类:

import cloudpickle
import pickletools
from myclass import SubClass


obj = SubClass()
with open("cloudpickle_object.pkl", "wb") as f:
    cloudpickle.dump(obj, f)

with open("cloudpickle_object.pkl", "rb") as infile:
    pickletools.dis(infile)
Run Code Online (Sandbox Code Playgroud)

输出仅引用子类,没有基类或代码:

    0: \x80 PROTO      4
    2: \x95 FRAME      27
   11: \x8c SHORT_BINUNICODE 'myclass'
   20: \x94 MEMOIZE    (as 0)
   21: \x8c SHORT_BINUNICODE 'SubClass'
   [...]
Run Code Online (Sandbox Code Playgroud)

Joã*_*ias 5

cloudpickle仅序列化属于模块一部分的对象,如其 github https://github.com/cloudpipe/cloudpickle__main__中所述。

因此,使用导入的 pickle 对象自然会更小,因为这些对象预计在 unpickle 时导入。

有趣的是,已经有一些功能请求和一些工作使 cloudpickle 序列化一些导入的模块。例如,