【问题标题】:Retrieve module object from stack frame从堆栈帧中检索模块对象
【发布时间】:2010-01-04 17:18:00
【问题描述】:

给定一个框架对象,我需要获取对应的模块对象。换句话说,实现 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__ 属性(也有代码对象),但它不存在于框架中。确实,并非所有代码对象都属于函数对象,例如我的测试用例的代码(上面带有断言)。对于没有模块的框架/代码对象也可以这样说——但它们中的许多都有,而且在我的情况下它们会,所以不需要处理;但是,在这种情况下,一个简单的 None 或异常也可以。

感觉好像我错过了一些简单的东西。为此需要做什么?

【问题讨论】:

    标签: python introspection


    【解决方案1】:

    虽然 inspect.getmodule 效果很好,但我确实在错误的地方找到它,但我找到了一个更好的解决方案:

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

    它仍然使用inspect.currentframe(我更喜欢完全相同的sys._getframe),但不调用inspect的模块文件名映射(在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"]
    

    【讨论】:

    • 现在我希望我可以使模块可调用并简化上面的示例:stackoverflow.com/questions/1060796/callable-modules
    • 如果您正在寻找带有模块名称的字符串,请注意。如果模块作为top-level script 执行,它将无法按预期工作,因为__name__ 将始终为__main__。为了涵盖所有情况,最好使用inspect.getmodule().__spec__.name,即使它是顶级脚本也会带来真正的模块名称。
    【解决方案2】:
    import inspect
    def callers_module():
       module = inspect.getmodule(inspect.currentframe().f_back)
       return module
    

    【讨论】:

      猜你喜欢
      • 2016-01-12
      • 1970-01-01
      • 2016-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      • 1970-01-01
      • 2017-05-07
      相关资源
      最近更新 更多