如何在 Python 中获得对当前模块属性的引用

我要做的事情在命令行中是这样的:

>>> import mymodule
>>> names = dir(mymodule)

如何从 mymodule本身获得对 mymodule中定义的所有名称的引用?

就像这样:

# mymodule.py
names = dir(__thismodule__)
110172 次浏览

只需使用 globals ()

Globals ()ー返回字典 表示当前全局符号的 这总是字典 当前模块(在 函数或方法,这是模块 定义它的地方,而不是模块 它被称为)。

Http://docs.python.org/library/functions.html#globals

正如前面提到的,globals 提供一个字典,而 dir ()提供模块中定义的名称列表。我通常的做法是这样的:

import sys
dir(sys.modules[__name__])

现在回答可能有点晚了,但我没有为自己找到正确的答案。 Python 3.7.x中最接近和最精确的解决方案(比 inspect.stack()快) :

# search for first module in the stack
stack_frame = inspect.currentframe()
while stack_frame:
print('***', stack_frame.f_code.co_name, stack_frame.f_code.co_filename, stack_frame.f_lineno)
if stack_frame.f_code.co_name == '<module>':
if stack_frame.f_code.co_filename != '<stdin>':
caller_module = inspect.getmodule(stack_frame)
else:
# piped or interactive import
caller_module = sys.modules['__main__']
if not caller_module is None:
#... do something here ...
break
stack_frame = stack_frame.f_back

优点 :

  • globals()方法更精确。
  • 不依赖于堆栈中间帧,例如,可以通过钩子或3dparty 工具(如 pytest)添加:
*** foo ... ..
*** boo ... ..
*** runtest c:\python\x86\37\lib\site-packages\xonsh\pytest_plugin.py 58
*** pytest_runtest_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 125
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** <lambda> c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** from_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 229
*** call_runtest_hook c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** call_and_report c:\python\x86\37\lib\site-packages\_pytest\runner.py 176
*** runtestprotocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 95
*** pytest_runtest_protocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 80
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** pytest_runtestloop c:\python\x86\37\lib\site-packages\_pytest\main.py 258
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** _main c:\python\x86\37\lib\site-packages\_pytest\main.py 237
*** wrap_session c:\python\x86\37\lib\site-packages\_pytest\main.py 193
*** pytest_cmdline_main c:\python\x86\37\lib\site-packages\_pytest\main.py 230
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** main c:\python\x86\37\lib\site-packages\_pytest\config\__init__.py 90
*** <module> c:\Python\x86\37\Scripts\pytest.exe\__main__.py 7
  • 可以处理 Python 管道或交互式会话。

缺点:

  • 一种非常精确并且可以返回在可执行文件中注册的模块,比如 pytest.exe,这可能不是你想要的。
  • 取决于挂钩,inspect.getmodule仍然可以在有效模块上返回“无”

我有一个蟒蛇的扩展: 如何导入模块给定的完整路径?

具有该情况下的包装函数的扩展:

def tkl_get_stack_frame_module_by_offset(skip_stack_frames = 0, use_last_frame_on_out_of_stack = False):
...


def tkl_get_stack_frame_module_by_name(name = '<module>'):
...

你必须正确地初始化扩展:

# portable import to the global space
sys.path.append(<path-to-tacklelib-module-directory>)
import tacklelib as tkl


tkl.tkl_init(tkl, global_config = {'log_import_module':os.environ.get('TACKLELIB_LOG_IMPORT_MODULE')})


# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()


# use `tkl_*` functions directly from here ...