gpt4 book ai didi

python - pickle:它如何 pickle 一个函数?

转载 作者:行者123 更新时间:2023-12-03 10:08:17 32 4
gpt4 key购买 nike

post昨天发帖,无意中发现改了__qualname__函数对 pickle 有意想不到的影响.通过运行更多测试,我发现在对函数进行 pickle 时,pickle不像我想的那样工作,改变 __qualname__函数的实际影响 pickle行为。
下面的片段是我运行的测试,

import pickle
from sys import modules

# a simple function to pickle
def hahaha(): return 1

print('hahaha',hahaha,'\n')

# change the __qualname__ of function hahaha
hahaha.__qualname__ = 'sdfsdf'
print('set hahaha __qualname__ to sdfsdf',hahaha,'\n')

# make a copy of hahaha
setattr(modules['__main__'],'abcabc',hahaha)
print('create abcabc which is just hahaha',abcabc,'\n')

try:
pickle.dumps(hahaha)
except Exception as e:
print('pickle hahaha')
print(e,'\n')

try:
pickle.dumps(abcabc)
except Exception as e:
print('pickle abcabc, a copy of hahaha')
print(e,'\n')

try:
pickle.dumps(sdfsdf)
except Exception as e:
print('pickle sdfsdf')
print(e)
正如您通过运行代码片段所看到的, hahahaabcabc由于以下异常不能 pickle : Can't pickle <function sdfsdf at 0x7fda36dc5f28>: attribute lookup sdfsdf on __main__ failed .
我真的对这个异常(exception)感到困惑,
  • pickle 是什么意思寻找它何时 pickle 一个功能?虽然 __qualname__hahaha改为'sdfsdf',函数hahaha及其副本abcabc在 session 中仍然可以调用(因为它们在 dir(sys.modules['__main__']) 中),那么为什么 pickle不能 pickle 它们吗?
  • 更改__qualname__的真正效果是什么?的功能?我理解通过更改 __qualname__hahaha到 'sdfsdf' 不会使 sdfsdf可调用,因为它不会出现在 dir(sys.modules['__main__']) 中.但是,正如您通过运行代码片段所看到的,在更改 __qualname__ 之后的 hahaha到 'sdfsdf',对象 hahaha及其副本abcabc已更改为 <function sdfsdf at 'some_address'> . sys.modules['__main__'] 中的对象有什么区别?和 <function sdfsdf at 'some_address'> ?
  • 最佳答案

    函数对象的 pickle 在 save_global method in pickle.py 中定义。 :
    首先,通过 __qualname__ 检索函数的名称:

    name = getattr(obj, '__qualname__', None)
    之后,在检索模块后,将其重新导入:
    __import__(module_name, level=0)
    module = sys.modules[module_name]
    这个新鲜进口的 module然后用于将函数作为属性查找:
    obj2, parent = _getattribute(module, name)
    obj2现在将是该函数的新副本,但由于 sdfsdf此模块中不存在, pickle 在这里失败。

    您可以完成这项工作,但您必须保持一致:
    >>> import sys
    >>> import pickle
    >>> def hahaha(): return 1
    >>> hahaha.__qualname__ = "sdfsdf"
    >>> setattr(sys.modules["__main__"], "sdfsdf", hahaha)
    >>> pickle.dumps(hahaha)
    b'\x80\x04\x95\x17\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x06sdfsdf\x94\x93\x94.'

    关于python - pickle:它如何 pickle 一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64095346/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com