J'ai un Python 3 dans lequel j'importe dynamiquement des modules à partir du disque, en utilisant imp.load_module
. Mais j'ai rencontré un problème où les importations relatives échouent, lorsque l'importation relative se produit à l'intérieur d'un module importé dynamiquement.
D'après ce que j'ai lu, j'en suis arrivé à la conclusion que seuls les __file__
, __path__
, __package__
y __name__
ont été utilisées par l'importateur par défaut pour déterminer le chemin d'une importation. Pourtant, j'ai vérifié ces éléments dans le code ci-dessous, et il échoue toujours lorsqu'il est importé dynamiquement. (Il fonctionne lorsqu'il est importé dans l'interpréteur avec un fichier sys.path
)
# File structure:
# [root]
# __init__.py
# board.py
# test.py
# Contents of 'board.py':
import os, sys
import root # Already imported... just need a reference
ROOT_DIR = os.path.dirname(root.__file__)
assert root is sys.modules['root']
assert root.__package__ is None
assert root.__name__ == 'root'
assert root.__file__ == os.path.join(ROOT_DIR, '__init__.py')
assert not hasattr(root, '__path__')
xx = object()
assert xx is sys.modules['root.board'].xx
assert __package__ is None
assert __name__ == 'root.board'
assert __file__ == os.path.join(ROOT_DIR, 'board.py')
assert not hasattr(sys.modules['root.board'], '__path__')
assert os.path.isfile(os.path.join(ROOT_DIR, 'test.py'))
from . import test # ImportError('cannot import name test',)
Mais si je pirate sys.path
et réimporter le paquet actuel juste avant l'échec de l'importation, cela fonctionne :
oldroot = root
del sys.modules['root']
sys.path.append(os.path.dirname(ROOT_DIR))
import root
from . import test # No error here
De plus, les quatre attributs en or mentionnés ci-dessus sont les mêmes dans les nouveaux et les anciens paquets :
assert oldroot.__package__ == root.__package__
assert oldroot.__name__ == root.__name__
assert oldroot.__file__ == root.__file__
assert not hasattr(root, '__path__')
Ce qui signifie que __package__
, __name__
, __file__
y __path__
ne peut pas tout expliquer. Existe-t-il d'autres attributs que Python utilise pour localiser les importations ? Qu'est-ce que j'ai négligé qui pourrait faire échouer l'importation ?