如何在模块内部获取对该模块的引用?

208

我该如何在模块内部获取对该模块的引用?此外,我如何获取包含该模块的包的引用?


7
我猜想你提出这个问题的原因可能是,你在代码的模块作用域中定义了一个变量(例如,在函数或类之外定义的BLAH=10),然后又在类/函数作用域中定义了一个名为BLAH的变量,现在你想要区分它们。一个合理的问题是:这样做必要吗?作用域规则很容易被误解,特别是由于“白痴”在你之后接手你的代码(例如在6个月之后)。这种技巧很少是必要的;我试图完全避免使用它们,因为它们常常会令人困惑,并在以后错误地修改。 - Kevin J. Rice
2
@KevinJ.Rice说:“在你之后(比如6个月后)接手你的代码的那个‘白痴’”让我开心了! - Arctelix
22
谁在乎他为什么提出这个问题?需要做这件事情的合理原因有很多。 - Christopher Barber
@Christopher:虽然这种情况并不经常出现,但这里有一个例子。 - martineau
8个回答

260
import sys
current_module = sys.modules[__name__]

3
如果重新加载模块,除非做一些修改,否则这不会完全正确;我认为没有任何地方可以保证引用的保留,如果有的话,重新加载就不会起作用,对吧? - Dima Tisnek
20
重新载入会重复使用同一个模块对象;不会创建新的模块对象,因此在重新加载时仍然正确。 - bukzor
谢谢,只有这个答案可以直接使用带点的模块路径。 - Dee

29

还有一种技术,不需要导入sys模块,并且根据你的口味可以认为更简单:

current_module = __import__(__name__)

请注意,Python 中不存在导入重复的情况。每个模块只会被导入一次。


这似乎是避免导入sys的一种不错的方式。除了阅读时有点反直觉之外,还有其他潜在的缺点吗? - JeremyDouglass
@JeremyDouglass。据我所知,没有。__import__是一个合法的、有文档支持的内置函数(唯一的__xx__函数)。您可以使用'importlib'包替换它(您需要导入它)。也许——从未发生过这种情况——如果sys.path中可用同名模块存在问题,则可以通过函数的' level '参数解决它。 - Uri London
4
这个解决方案在我的代码上不起作用。它创建指向包而不是模块的引用。我是唯一一个遇到这种情况的人吗? - sangorys
3
我也遇到了这种行为(获取包的引用而不是模块)在 Python 3.9 上。 - blthayer
4
根据文档字符串:“从包中导入模块时,请注意__import__('A.B', ...)在fromlist为空时返回包A,但在fromlist不为空时返回其子模块B。”同样建议在同一处使用importlib.import_module,该函数不具有这种行为。 - Sargera
2
不要使用此答案,它会让你感到困惑,因为它的行为不够直观,有时会导入比指定的更高层次的模块。详情请参见:stackoverflow.com/a/37308413/210867。 - odigity

17

如果该模块中有一个类,则该类的 __module__ 属性是该类所在的模块名称。因此,您可以通过 sys.modules [klass.__module__] 访问该模块。这对于函数也适用。


15

使用 __name__ 可以获取当前模块的名称。

模块引用可以在 sys.modules 字典中找到。

请查看 Python 文档


4
根据@truppo的回答这个回答(以及PEP366): 引用此 模块
import sys
this_mod = sys.modules[__name__]

对 "this" 的引用:

import sys
this_pkg = sys.modules[__package__]

__package____name__ 如果来自(顶层)的 __init__.py 文件,则相同。


3
你可以从外部传递它:

你可以从外部传递它:

mymod.init(mymod)

虽然不是理想情况,但对于我目前的使用场景来说可行。


1
如果您只需要访问模块变量,那么请使用globals()['bzz'](如果是模块级别,请使用vars()['bzz'])。


0
from importlib import import_module
current_module = import_module(__name__)

附注:还可以参考Sargera的评论


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接