RexE
RexE

Reputation: 17723

Why does this snippet with import_module fail?

The following code creates a Python package a.b.c, then tries to import it. It fails, but works fine if I comment out the line import_module('a.b') inside the try/except!

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')

When i run it on my Mac (official Python 3.6 installation), I get:

<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'

This issue only happens on my Mac, not my Windows Python 3.6.

It seems that on Mac, the import_module is adding a to sys.modules; I think this could be connected to why the later import fails.

Upvotes: 1

Views: 1317

Answers (1)

ritlew
ritlew

Reputation: 1682

It would appear that importlib caches the result of your failed import of a.b. When you try to import a.b.c it already thinks a.b doesn't exist, even though you created it. You would have to call invalidate_caches() from the importlib package before trying to import again.

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

If you are dynamically importing a module that was created since the interpreter began execution (e.g., created a Python source file), you may need to call invalidate_caches() in order for the new module to be noticed by the import system.

Upvotes: 1

Related Questions