Python:除了pickle模块,还有哪些替代方案?

3
我正在开发我的程序GarlicSim,用户可以创建一个模拟,然后按照他的需求对其进行操作,最后可以将其保存到文件中。
我最近尝试实现保存功能。自然而然地想到的是使用pickle对包含整个模拟的Project对象进行序列化。
问题是,Project对象还包括一个模块——即“模拟包”,它是一个包/模块,包含了定义模拟的几个关键对象(主要是函数)。我需要将它们与模拟一起保存,但似乎无法对模块进行pickle,因为当我尝试pickle Project对象时引发了异常。
有什么好的方法来解决这个限制呢?
(我还应该注意到,模拟包在程序中动态导入。)
2个回答

2
如果项目中有一个引用到你需要的模块的地方,那么你可能希望将该模块的使用重构为模块中的一个类。这通常是更好的选择,因为在模块中使用全局变量的应用程序结构会导致问题。当然,解决方法可以是保存模块的字典而不是直接保存模块本身。

你的意思是,不是引用动态导入的模块,而是引用在动态导入的模块内定义的类? - Ram Rachum
是的,动态实例化一个类似乎比动态导入一个模块更加简洁。 - djc
有趣。但我认为这有些问题。我的程序工作方式是用户选择要导入哪个模拟包。也就是说,不同类型的模拟(例如牛顿物理学、博弈论等)都有预先编写好的模拟包。您建议我只在这些预先编写的包中定义一个类,并将所有对象作为其属性吗? - Ram Rachum
那听起来是一种方法,但是如果不了解您的包如何完全配合,很难说。如果您想最小化修改代码,可以在不同包中使用具有公认名称(例如每个模块中相同的名称)的单个类,并仍然执行动态导入操作。 - djc
2
模块不应该有状态。类应该有状态。保存对象会保存类的状态。这就是它应该工作的方式。您可以将复杂的模拟“包装”在一个Facade类中,该类封装了整个模拟,并可以作为“单个”事物持久化。其中还有许多其他对象。 - S.Lott

1
如果你有模拟包模块的原始代码,我假设这些代码是动态生成的,那么我建议将其序列化并在加载时重新构建模块。你可以在Project.__getstate__()Project.__setstate__()方法中实现这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接