gpt4 book ai didi

python - 使用属性序列化函数对象,加载时缺少一个属性

转载 作者:行者123 更新时间:2023-12-01 07:35:58 26 4
gpt4 key购买 nike

我在 python 3.7 中使用 dill,但是当我稍后重新加载它时,函数的属性之一丢失了。

我有一个名为 session 的类,我在程序退出时保存它,在启动时加载它。该对象间接包含 Tranform 实例,这些实例具有引用特定函数的 function 属性。该函数设置了多个属性。

当我在保存 session 时使用调试器时,我可以看到特定属性存在并设置为None。但是,当我加载已保存的 session 时,一切都很好,只是这个属性消失了。

这是保存代码:

def save(self):
print ('\n SAVING SESSION STATE, DO NOT EXIT')
breakpoint()

sessionDirectory='__PETL__'
if not os.path.exists(sessionDirectory):
os.makedirs(sessionDirectory)
with open(sessionDirectory+'/'+self.name, 'wb') as f:
dill.dump(self,f)
print ('\nSession Saved, exiting')

这是加载代码:

def loadSession(self, sessionName):
if (Session.dontLoad):
print ('Creating New Session')
return None
try:
with open('__PETL__/'+ sessionName, 'rb') as f:
session=dill.load(f)
except FileNotFoundError:
print ('No session found, creating new one')
return None

return session

这是调试器输出:

保存:

> /home/osboxes/stage/inspireDataBase2/migrations/src/session/session.py(160)save()
-> sessionDirectory='__PETL__'
(Pdb) print( self.transforms[0].transform.function.queryRes)
None
(Pdb) print (dir(self.transforms[0].transform.function)[-9:])
['after', 'args', 'columns', 'fetch', 'indexs', 'query', 'queryRes', 'sameorderasafter', 'transformvar']
(Pdb) dill.dumps(self.transforms[0].transform.function)
b'\x80\x03cuserTransformModulePreparsed\ntransform__constru__buildinggeometry2d\nq\x00.'
(Pdb) c
Session Saved, exiting

加载中:

> /home/osboxes/stage/inspireDataBase2/migrations/src/session/session.py(39)__init__()
-> session.printJobDone()
(Pdb) print( self.transforms[0].transform.function.queryRes)
*** AttributeError: 'function' object has no attribute 'queryRes'
(Pdb) print( session.transforms[0].transform.function.queryRes)
*** AttributeError: 'function' object has no attribute 'queryRes'
(Pdb) print (dir(session.transforms[0].transform.function)[-9:])
['__subclasshook__', 'after', 'args', 'columns', 'fetch', 'indexs', 'query', 'sameorderasafter', 'transformvar']

如您所见,其他属性按预期工作。

由于保存部分是我在项目中做的最后一件事,我想我只是不明白 dill 是如何工作的。该属性与另一个不同,因为该属性是在另一个类中设置的(与函数不在同一模块中)。其他属性直接在函数的模块中设置。也就是说,该模块是通过编译 AST Tree 获得的,但我不明白为什么会出现问题。

我发现确实在第一个输出中,在 dill 输出中只有对函数模块的引用(但我不知道 dill 是如何工作的,也许这是正常的)。

最佳答案

dill 不捕获函数属性,不适用于可直接导入的函数。您在加载时看到的任何属性都是由其他代码添加到该函数对象的,也许是在导入时添加的。

存储的所有 dill.dumps() 信息足以重新导入相同的函数对象;在调试 session 中,它是 userTransformModulePreparsed.transform__constru__buildinggeometry2d。加载该序列化时,需要做的就是import userTransformModulePreparsed,然后使用该模块的transform__constru__buildinggeometry2d属性。在这种情况下,函数被视为单例,每个 Python 进程只需要存在一个副本。假设该对象的所有加载均由正常的导入过程处理。这包括添加到函数对象的属性!

dill 可以处理生成的函数对象,即任何不能直接导入的函数对象,此时它'将捕获函数的所有方面,包括属性。例如,在函数(嵌套函数)内部使用 def 每次调用父函数时都会创建一个新的、单独的函数对象。序列化此类对象的处理方式有所不同:

>>> import dill
>>> def foo():
... def bar(): pass # nested function
... bar.spam = 'ham'
... return bar
...
>>> foo()
<function foo.<locals>.bar at 0x110621e50>
>>> foo() is not foo() # new calls produce new function objects
True
>>> bar = foo()
>>> vars(bar) # the resulting function object has attributes
{'spam': 'ham'}
>>> bar_restored = dill.loads(dill.dumps(bar))
>>> vars(bar_restored) # the attributes are preserved by dill
{'spam': 'ham'}
>>> bar.extra = 'additional'
>>> vars(dill.loads(dill.dumps(bar))) # this extends to new attributes added later.
{'spam': 'ham', 'extra': 'additional'}

所以你这里有两个选择;在导入时设置函数属性,在嵌套函数中生成函数。

关于python - 使用属性序列化函数对象,加载时缺少一个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56991769/

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