从堆栈帧中检索模块对象

时间:2010-01-04 17:18:01

标签: python introspection

给定一个框架对象,我需要获取相应的模块对象。换句话说,实现callers_module,这样就可以了:

import sys
from some_other_module import callers_module
assert sys.modules[__name__] is callers_module()

(这是等效的,因为我可以在这个测试用例的函数中生成一个堆栈跟踪。导入只是为了让这个例子完整和可测试,并防止callers_module采用__name__的快捷方式,因为它在一个不同的模块。)

我试过这个:

import inspect
def callers_module():
  return inspect.currentframe().f_back

获取一个框架对象,f_code将在其上提供代码对象,但我无法找到如何获取相应的模块或其名称(与sys.modules一起使用)。如果我可以获得函数对象,那些函数具有__module__属性(并且还具有代码对象),但是框架中不存在这些属性。实际上,并非所有代码对象都属于函数对象,例如我的测试用例的代码(上面带有assert)。对于没有模块的框架/代码对象也可以这么说 - 但是很多都是这样做的,在我的情况下它们会这样做,因此不需要处理;但是,在这种情况下,一个简单的无或例外也可以。

感觉我错过了一些简单的事情。需要做些什么才能发挥作用?

2 个答案:

答案 0 :(得分:6)

虽然inspect.getmodule工作得很好,而且我确实找错了地方找到它,但我找到了一个更好的解决方案:

def callers_module():
  module_name = inspect.currentframe().f_back.f_globals["__name__"]
  return sys.modules[module_name]

它仍然使用inspect.currentframe(我更喜欢完全相同的sys._getframe),但不调用inspect的module-filename映射(在inspect.getmodule中)。

此外,这个问题激发了manage __all__的有趣方式:

from export import export

@export
class Example: pass

@export
def example: pass

answer = 42
export.name("answer")

assert __all__ == ["Example", "example", "answer"]

答案 1 :(得分:2)

import inspect
def callers_module():
   module = inspect.getmodule(inspect.currentframe().f_back)
   return module