【问题标题】:function to pickle all objects from a given module从给定模块中腌制所有对象的函数
【发布时间】:2012-11-21 08:03:29
【问题描述】:

我想编写一个函数来腌制当前命名空间中的所有对象,这些对象是给定模块中类的实例。这个想法是,在 ipython 会话期间,用户从mymodule 创建了许多对象,并且可能需要快速保存所有对象。

所以,例如我想要这样的东西

from mymodule import cat, dog, pickle_all
c= cat(), d=dog()
pickle_all('killer_sesh.p')

结束会话,忘记一个月,回来开始新的会话,

from mymodule import upickle_all 
objs = unpickle_all('killer_sesh.p')

所以我的第一次尝试(如下所示)在粘贴到当前命名空间时有效。如果我定义为一个函数,或者把它放在其他地方,比如在 mymodule 中,那么dir() 命令不会返回当前命名空间,而是返回函数所看到的命名空间。即使我将 dir() 的结果作为参数传递,对象在函数中也不可用。

import pickle
filename= 'killer_sesh.p'
module='mymodule'
module_objects = {}
for k in dir():
    try:
        if eval(k).__module__.split('.')[0] == module:
            if k[0]!='_':
                print(k)
                module_objects[k] = eval(k)
    except(AttributeError):
        pass
    file= open(filename,'w')
pickle.dump(module_objects, file)
file.close()

这样的功能可行吗?

【问题讨论】:

  • 你不应该使用eval() 来做这样的事情——这是一种糟糕的方法。看看getattr()
  • +1 对 Lattyware 的评论。此外,您可能希望使用 inspect 模块,而不是手动迭代 dir 并弄清楚如何处理它。
  • 这些都是很好的建议,但真正的问题是访问函数命名空间之外的对象。
  • @alex:你需要引用那个命名空间。一旦你有了它,你就可以使用inspectgetattr 来访问其中的对象。如果你没有它,但你有一些东西可以用来访问它(例如,你可以用sys.modules[name] 查找的模块的名称),或者足以伪造它(globals()locals()从该命名空间调用),也可以。但除此之外,没有办法访问这些对象,也没有任何办法可以提供帮助。 (如果您来自 JS,Python 没有作为默认上下文的全局 window 对象。)

标签: python namespaces scope ipython pickle


【解决方案1】:

如果我定义为一个函数,或者把它放在其他地方,比如在 mymodule 中,那么 dir() 命令不会返回当前命名空间,而是返回函数看到的命名空间。即使我将 dir() 的结果作为参数传递,对象在函数中也不可用。

对,那是因为您使用 eval 来评估它们,它会在当前命名空间中评估它们。您可以从不同的主空间传递globalslocals,并使用这些参数调用eval。换句话说,不是foo(dir()),而是foo(dir(), globals(), locals())`。

但是,整个设计是个坏主意。使用eval 获取作用域的成员是个坏主意。事实上,对几乎任何事情使用eval 是个坏主意。

一个更好的解决方案是传递你想要评估成员的东西,并使用getattr 来获取它们。

一个更好的解决方案是避免使用dir,然后弄清楚如何使用这些名称获取属性;如果您想检查事物,这就是 inspect 模块的用途。 (即使你想做一些inspect 没有提供的东西,阅读它的源代码——从文档链接——通常会告诉你最好的方法。)

【讨论】:

  • 传递locals()的输出解决了命名空间问题,inspect模块确实对确定源模块很有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 2018-10-18
  • 2020-12-31
  • 2012-09-08
  • 1970-01-01
  • 2017-10-08
相关资源
最近更新 更多