每次程序运行时都会使用不同的cloudpickle

2024-03-29 14:37:01 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑下面的Python代码:

import cloudpickle


class Foo:
    def __init__(self, num):
        self.num = num


def outer(num):
    return Foo(num)


print(cloudpickle.dumps(outer))

这会在每次运行代码时产生不同的pickle。使用pickletools分析pickle文件显示以下差异:

144c144
<   552: \x8c         SHORT_BINUNICODE '2e3db4572bb349268962a75a8a6f034c'
---
>   552: \x8c         SHORT_BINUNICODE '89ee770de9b745c4bbe83c353f1debba'

现在,我知道cloudpickle不能保证pickle文件的确定性。(link),但我很好奇为什么这两个pickle文件不同。上面的差异似乎是由于Foo类的某种不同哈希造成的

注意,我使用固定的PYTHONHASHSEED运行python程序

附言: 这足以重现问题:

import pickletools
import cloudpickle


class Foo:
    def __init__(self, num):
        self.num = num


pickletools.dis(cloudpickle.dumps(Foo))

因此,似乎每个类都有一个属性,该属性被烘焙到cloudpickle中,但我不知道该属性是什么


1条回答
网友
1楼 · 发布于 2024-03-29 14:37:01

好奇

我深入研究了源代码,发现它不是类的属性,甚至不是计算的哈希,而是just a random identifier generated with ^{} per class

该函数由^{} here调用,该函数由具有注释的^{} here调用

Save a class that can't be stored as module global. This method is used to serialize classes that are defined inside functions, or that otherwise can't be serialized as attribute lookups from global modules.

如果类不在__main__模块中,事情就不会那么复杂了(因为__main__从最终的unpickler的角度来看可能是任何东西);如果你做了from b import outer和cloudpickleouter,你会得到

    0: \x80 PROTO      5
    2: \x95 FRAME      15
   11: \x8c SHORT_BINUNICODE 'b'
   14: \x94 MEMOIZE    (as 0)
   15: \x8c SHORT_BINUNICODE 'outer'
   22: \x94 MEMOIZE    (as 1)
   23: \x93 STACK_GLOBAL
   24: \x94 MEMOIZE    (as 2)
   25: .    STOP

就像泡菜,而不是巫毒云泡菜,用来泡菜__main__中的东西一样

相关问题 更多 >