10

给定一个框架对象,我需要获取相应的模块对象。换句话说,实现 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 或异常也可以。

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

4

2 回答 2

12

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

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

It still uses inspect.currentframe (which I prefer over the exactly identical sys._getframe), but doesn't invoke inspect's module-filename mapping (in inspect.getmodule).

Additionally, this question inspired an interesting way to manage __all__:

from export import export

@export
class Example: pass

@export
def example: pass

answer = 42
export.name("answer")

assert __all__ == ["Example", "example", "answer"]
于 2010-01-06T05:44:56.867 回答
5
import inspect
def callers_module():
   module = inspect.getmodule(inspect.currentframe().f_back)
   return module
于 2010-01-04T17:50:39.380 回答