【发布时间】:2020-09-28 02:50:24
【问题描述】:
在我昨天发的一个post中,无意中发现改变一个函数的__qualname__对pickle有意想不到的效果。通过运行更多的测试,我发现在 pickling 一个函数时,pickle 并没有像我想象的那样工作,而更改函数的 __qualname__ 对 pickle 的行为方式有真正的影响。
下面的sn-ps是我跑的测试,
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)
运行 sn-ps 可以看到,hahaha 和 abcabc 都不能因为异常而被腌制:
Can't pickle <function sdfsdf at 0x7fda36dc5f28>: attribute lookup sdfsdf on __main__ failed.
我真的被这个异常弄糊涂了,
-
pickle在腌制函数时会寻找什么?尽管hahaha的__qualname__已更改为'sdfsdf',但函数hahaha及其副本abcabc仍然可以在会话中调用(因为它们在dir(sys.modules['__main__'])中),那么为什么pickle不能腌制吗? -
更改函数的
__qualname__的真正效果是什么?我理解通过将hahaha的__qualname__更改为“sdfsdf”不会使sdfsdf可调用,因为它不会出现在dir(sys.modules['__main__'])中。但是,正如您通过运行 sn-ps 所看到的,在将hahaha的__qualname__更改为“sdfsdf”后,对象hahaha及其副本abcabc已更改为类似于<function sdfsdf at 'some_address'>的内容。sys.modules['__main__']和<function sdfsdf at 'some_address'>中的对象有什么区别?
【问题讨论】:
标签: python python-3.x pickle