Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
253 views
in Technique[技术] by (71.8m points)

python - Retrieve module object from stack frame

Given a frame object, I need to get the corresponding module object. In other words, implement callers_module so this works:

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

(That would be equivalent because I can generate a stack trace in the function for this test case. The imports are there simply to make that example complete and testable, and prevent callers_module from taking the shortcut of using __name__, since it's in a different module.)

I've attempted this:

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

Which gets a frame object, on which f_code will give me a code object, but I can't find out how to get the corresponding module or its name (to use with sys.modules). If I could get function objects, those have a __module__ attribute (and also have code objects), but that's not present in the frame. Indeed, not all code objects belong to function objects, such as the code for my test case (with assert, above). The same can be said of frame/code objects not having a module—but many of them do, and in my case they will, so that doesn't need to be handled; however, a simple None or exception is fine in that case, too.

It feels like I'm missing something simple. What needs to be done for this to work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While inspect.getmodule works great, and I was indeed looking in the wrong place to find it, I found a slightly better solution for me:

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"]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...