Python 从堆栈帧中检索模块对象

Python 从堆栈帧中检索模块对象,python,introspection,Python,Introspection,给定一个frame对象,我需要得到相应的module对象。换句话说,实现callers_模块以使其工作: import sys from some_other_module import callers_module assert sys.modules[__name__] is callers_module() (这是等效的,因为我可以在此测试用例的函数中生成堆栈跟踪。导入只是为了使该示例完整且可测试,并防止调用方\u模块采用使用\u名称\u的快捷方式,因为它位于不同的模块中。) 我尝试过:

给定一个frame对象,我需要得到相应的module对象。换句话说,实现callers_模块以使其工作:

import sys
from some_other_module import callers_module
assert sys.modules[__name__] is callers_module()
(这是等效的,因为我可以在此测试用例的函数中生成堆栈跟踪。导入只是为了使该示例完整且可测试,并防止调用方\u模块采用使用\u名称\u的快捷方式,因为它位于不同的模块中。)

我尝试过:

import inspect
def callers_module():
  return inspect.currentframe().f_back
它得到一个frame对象,f_代码会给我一个code对象,但我不知道如何得到相应的模块或其名称(用于sys.modules)。如果我可以得到函数对象,它们有一个_模块_)属性(也有代码对象),但在框架中不存在。事实上,并非所有的代码对象都属于函数对象,比如我的测试用例的代码(上面带有assert)。对于没有模块的框架/代码对象也可以这样说,但它们中的许多都有模块,在我的例子中,它们会有模块,因此不需要处理模块;然而,在这种情况下,简单的“无”或“例外”也可以


我觉得我错过了一些简单的事情。需要做些什么才能使其正常工作?

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

import inspect
def callers_module():
   module = inspect.getmodule(inspect.currentframe().f_back)
   return module
def callers_module():
  module_name = inspect.currentframe().f_back.f_globals["__name__"]
  return sys.modules[module_name]
它仍然使用inspect.currentframe(我更喜欢它而不是完全相同的sys.\u getframe),但不调用inspect的模块文件名映射(在inspect.getmodule中)

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


现在,我希望我可以使模块可调用,并简化上面的示例:如果要查找具有模块名称的字符串,请小心。如果将模块作为执行,它将无法按预期工作,因为
\uuuuu name\uuuuuu
将始终是
\uuuuuuu main\uuuuu
。为了涵盖所有情况,最好使用
inspect.getmodule().\uuuu spec\uuuu.name
,即使是顶级脚本,它也会带来真正的模块名称。
from export import export

@export
class Example: pass

@export
def example: pass

answer = 42
export.name("answer")

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