from ... import ... 对sys.modules的影响

2020年1月3日 / 62次阅读 / Last Modified 2020年1月16日
sys模块语法

前一篇总结python的import module机制,感觉没有说完,还有重要细节,即如果采用 from ... import ... 的方式向当前namespace引入符号,对sys.modules的影响是什么?

先说结论:在sys.modules中,依然保存的是整个模块,而引入当前namespace的,只是import后面的符号而已!

有一个模块test_import.py,内有如下代码:

$ cat test_import.py

a = 1
b = 2
def test(): pass
class cc(): pass

现在我们在python解释器中做import试试:

>>> from test_import import cc
>>> 'cc' in locals().keys()
True
>>> import sys
>>> for k in sys.modules.keys(): print(k)
...
sys
builtins
_frozen_importlib
_imp
_thread
_warnings
_weakref
zipimport
_frozen_importlib_external
_io
marshal
posix
encodings
codecs
_codecs
encodings.aliases
encodings.utf_8
_signal
__main__
encodings.latin_1
io
abc
_abc
site
os
stat
_stat
posixpath
genericpath
os.path
_collections_abc
_sitebuiltins
readline
atexit
rlcompleter
test_import

cc被引入当前namespace,而在sys.modules中,我们能找到test_import模块(最后一行)。

因此,我们可以说,sys.modules中保存的都是整个模块的入口,而哪一部分引入namespace,都可以,要看具体使用的是import module,还是 from ... import ... 。

我们再做一个测试,如果 from ... import ... 一个不存在的符号,对sys.modules的影响是什么?

还是直接先上结论:解释器会报错,ImportError,不过sys.modules中会保留这个模块。

>>> import sys
>>> for k in sys.modules.keys(): print(k)
...
sys
builtins
_frozen_importlib
_imp
_thread
_warnings
_weakref
zipimport
_frozen_importlib_external
_io
marshal
posix
encodings
codecs
_codecs
encodings.aliases
encodings.utf_8
_signal
__main__
encodings.latin_1
io
abc
_abc
site
os
stat
_stat
posixpath
genericpath
os.path
_collections_abc
_sitebuiltins
readline
atexit
rlcompleter
>>> from test_import import ddd
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'ddd' from 'test_import' (/home/xinlin/test/test_import.py)
>>> for k in sys.modules.keys(): print(k)
...
sys
builtins
_frozen_importlib
_imp
_thread
_warnings
_weakref
zipimport
_frozen_importlib_external
_io
marshal
posix
encodings
codecs
_codecs
encodings.aliases
encodings.utf_8
_signal
__main__
encodings.latin_1
io
abc
_abc
site
os
stat
_stat
posixpath
genericpath
os.path
_collections_abc
_sitebuiltins
readline
atexit
rlcompleter
test_import

一开始在sys.modules中没有test_import模块,执行from test_import import ddd失败,因为没有ddd这个符号。然后再次检查sys.modules,发现了test_import。

补充一个网上截的from ... import ... 的流程图:

from ... import ... 的流程图
from ... import ... 的流程图

创建module B,就是执行B中的表达式,填充__dict__对象(sys.modules)。

-- EOF --

本文链接:https://www.pynote.net/archives/1693

留言区

《from ... import ... 对sys.modules的影响》有3条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    载入内存的模块都在sys.modules里面记录着,不同的namespace中能够引用的模块或模块的成员各不相同。 [回复]

  • 麦新杰

    扩展知识: Python在import其它模块时,是从sys.path中搜索的。 sys.path的初始值会受到PYTHONPATH、PYTHONHOME等环境变量的影响。 也可以在脚本运行过程中动态修改sys.path从而import自己需要的模块。 [回复]

  • 麦新杰

    Python中所有加载到内存的模块都放在sys.modules。当import一个模块时首先会在这个列表中查找是否已经加载了此模块,如果加载了则只是将模块的名字加入到正在调用import的模块的Local名字空间中。如果没有加载则从sys.path目录中按照模块名称查找模块文件,模块文件可以是py、pyc、pyd,找到后将模块载入内存,并加入到sys.modules中,并将名称导入到当前的Local名字空间。 [回复]


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top