给定一个框架对象,我需要获取相应的模块对象.换句话说,实现callers_module,这样可以:
import sys
from some_other_module import callers_module
assert sys.modules[__name__] is callers_module()
Run Code Online (Sandbox Code Playgroud)
(这将是等效的,因为我可以生成在此测试情况下,函数的堆栈跟踪.进口在那里只是为了让这个例子完整和可测试性,并防止callers_module采取使用__name__的快捷方式,因为它是在不同的模块.)
我试过这个:
import inspect
def callers_module():
return inspect.currentframe().f_back
Run Code Online (Sandbox Code Playgroud)
哪个得到一个框架对象,f_code会给我一个代码对象,但我找不到如何获取相应的模块或其名称(与sys.modules一起使用).如果我可以获取函数对象,那些函数具有__module__属性(并且还具有代码对象),但是框架中不存在这些属性.实际上,并非所有代码对象都属于函数对象,例如我的测试用例的代码(上面带有assert).对于没有模块的框架/代码对象也可以这么说 - 但是很多都是这样做的,在我的情况下它们会这样,所以不需要处理; 但是,在这种情况下,一个简单的无或例外也可以.
感觉我错过了一些简单的东西.需要做些什么才能工作?
小智 7
虽然inspect.getmodule效果很好,而且我确实找错了地方找到它,但我找到了一个稍好的解决方案:
def callers_module():
module_name = inspect.currentframe().f_back.f_globals["__name__"]
return sys.modules[module_name]
Run Code Online (Sandbox Code Playgroud)
它仍然使用inspect.currentframe(我更喜欢完全相同的sys._getframe),但不调用inspect的module-filename映射(在inspect.getmodule中).
此外,这个问题激发了一种管理__all__的有趣方式:
from export import export
@export
class Example: pass
@export
def example: pass
answer = 42
export.name("answer")
assert __all__ == ["Example", "example", "answer"]
Run Code Online (Sandbox Code Playgroud)
import inspect
def callers_module():
module = inspect.getmodule(inspect.currentframe().f_back)
return module
Run Code Online (Sandbox Code Playgroud)