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


Answers:


135

只需使用globals()

globals()—返回表示当前全局符号表的字典。这始终是当前模块的字典(在函数或方法内部,这是定义它的模块,而不是从中调用它的模块)。

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


4
有什么方法可以访问调用模块的gloabals()而不是定义模块?
dimo414

9
您可以尝试从traceback模块(docs.python.org/library/traceback.html)获取调用者的全局变量,但这正在进入黑暗的魔力领域。我不知道您要做什么,但是如果需要,您可能想重新考虑您的设计。
Maciej Pasternacki 2012年

一个典型的案例是“我需要X(完成Y)->您不需要X,您需要Z”。我确实需要X!没有冒犯,我只是觉得这很有趣,投票最多的答案给了我我所需要的答案:)
pawamoy19年

需要特别注意的是,globals()可能会返回错误的结果,因为它取决于被调用的上下文。例如,如果从类函数进行调用,则它将返回链接到该类的全局上下文,而不是当前模块上下文,这是明显不同的事情。即使从自由函数进行调用,它也可以返回不同的模块全局上下文,具体取决于函数的导入方式。
安德里(Andry)

163

如前所述,全局变量为您提供字典,而dir()则为您提供了模块中定义的名称列表。我通常看到的完成方式是这样的:

import sys
dir(sys.modules[__name__])

2
我要添加一条评论,即该命令不适用于' main '模块(在终端上运行的模块称为该模块),因为它似乎未在sys.modules中列出-但它确实可以工作:)
markm

但是,它似乎不适用于ipdb(将“ import ipdb; ipdb.set_trace()”插入文件中)。
gatoatigrado 2012年

9
优秀的!这只是允许我将当前模块的文档字符串用作用法消息- sys.modules[__name__].__doc__
乔治

并获得超级hacky。operators.attrgetter('module.attribute')(sys.modules[__name__])-您知道,如果您做疯狂的事情,人们会告诉您不要这样做,例如从字符串动态导入程序包,然后在不属于类或任何内容的情况下进行猴子补丁…
casey

2
对于任何阅读george注释的人:sys.modules[__name__].__doc__==,__doc__因为这是在当前名称空间中定义的。因此,不需要获取模块对象以访问其自身的属性。
奥利弗·贝斯特沃特

1

回答可能为时已晚,但我没有为自己找到正确的答案。inspect.stack()python中最接近,最精确的解决方案(比更快)3.7.x

  # 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 在有效模块上仍然可能会返回None,具体取决于挂钩

我对python进行了扩展: 如何在给定完整路径的情况下导入模块?

该扩展具有包装功能的情况:

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 ...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.