Tout d'abord, c'était une excellente question et une excellente occasion d'apprendre quelque chose de nouveau sur le système d'importation de Python. Alors creusons un peu !
Si l'on considère la mise en œuvre de pkgutil.get_data
nous voyons quelque chose comme ceci :
def get_data(package, resource):
spec = importlib.util.find_spec(package)
if spec is None:
return None
loader = spec.loader
if loader is None or not hasattr(loader, 'get_data'):
return None
# XXX needs test
mod = (sys.modules.get(package) or
importlib._bootstrap._load(spec))
if mod is None or not hasattr(mod, '__file__'):
return None
# Modify the resource name to be compatible with the loader.get_data
# signature - an os.path format "filename" starting with the dirname of
# the package's __file__
parts = resource.split('/')
parts.insert(0, os.path.dirname(mod.__file__))
resource_name = os.path.join(*parts)
return loader.get_data(resource_name)
La réponse à votre question se trouve dans cette partie du code :
mod = (sys.modules.get(package) or
importlib._bootstrap._load(spec))
Il examine les paquets déjà chargés et si le paquet que nous recherchons ( module.submodule
dans cet exemple) existe, il l'utilise et si ce n'est pas le cas, il essaie de charger le paquet à l'aide de la fonction importlib._bootstrap._load
.
Examinons donc les la mise en œuvre de importlib._bootstrap._load
pour voir ce qui se passe.
def _load(spec):
"""Return a new module object, loaded by the spec's loader.
The module is not added to its parent.
If a module is already in sys.modules, that existing module gets
clobbered.
"""
with _ModuleLockManager(spec.name):
return _load_unlocked(spec)
Eh bien, il est juste là ! La doc dit "Le module n'est pas ajouté à son parent".
Cela signifie que le submodule
est chargé mais il n'est pas ajouté au module module
module. Ainsi, lorsque nous essayons d'accéder au module submodule
via module
il n'y a pas de connexion, d'où le AtrributeError
.
Il est logique que la get_data
pour utiliser cette fonction car elle ne demande qu'un autre fichier dans le paquet et il n'est pas nécessaire d'importer tout le paquet et de l'ajouter à son parent et au parent de ses parents, etc.
Pour le voir vous-même, je vous suggère d'utiliser un débogueur et de placer des points d'arrêt. Vous pourrez ainsi voir ce qui se passe étape par étape.