为什么带有import_module的代码段失败?

时间:2018-01-11 17:57:40

标签: python macos python-import

以下代码创建一个Python包a.b.c,然后尝试导入它。它失败了,但是如果我在try / except!

中注释掉import_module('a.b')行,则可以正常工作
import os.path
from importlib import import_module
import os
import shutil
import sys

shutil.rmtree('a', ignore_errors=True)

os.makedirs('a')
with open('a/__init__.py', 'w'):
    pass

try:
    # it works if i comment out the following line!
    import_module('a.b')
    pass
except ImportError:
    pass
print(sys.modules.get('a'))

os.makedirs('a/b/c')

with open('a/b/__init__.py', "w"):
    pass

with open('a/b/c/__init__.py', "w"):
    pass

import_module('a.b.c')
print('ok')

当我在我的Mac(官方Python 3.6安装)上运行它时,我得到:

<module 'a' from '/Users/chris1/Documents/a/__init__.py'>
Traceback (most recent call last):
  File "/Users/chris1/Documents/foo3.py", line 35, in <module>
    import_module('a.b.c')
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 978, in _gcd_import
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 936, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 978, in _gcd_import
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 948, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'a.b'

此问题仅发生在我的Mac上,而不是我的Windows Python 3.6。

似乎在Mac上,import_module正在向a添加sys.modules;我认为这可能与后来导入失败的原因有关。

1 个答案:

答案 0 :(得分:0)

importlib似乎会缓存a.b导入失败的结果。当您尝试导入a.b.c时,它已经认为a.b不存在,即使您已创建它。在尝试再次导入之前,您必须从invalidate_caches()包中调用importlib

参考:https://docs.python.org/3/library/importlib.html#importlib.import_module

  

如果您要动态导入自创建以来创建的模块   解释器开始执行(例如,创建了一个Python源文件),你   可能需要调用invalidate_caches()才能使用新模块   进口系统注意到了。