Étant donné que j'ai la structure de répertoires suivante avec .
étant le répertoire de travail actuel
.
\---foo
\---bar
\---__init__.py
\---baz.py
Quand je lance python -c "import foo.bar.baz"
Je reçois
Traceback (most recent call last):
File "<string>", line 1
ImportError: No module named foo.bar.baz
Si je echo "" > foo/__init__.py
, la commande ci-dessus fonctionne.
Suis-je en train de faire quelque chose de mal ou ai-je mal compris le point de __init__.py
? Je pensais que c'était pour empêcher les modules d'exister là où ils ne devraient pas, par exemple un répertoire nommé string
, mais si vous remplacez foo
par string
dans mon exemple, je suis apparemment obligé de créer le module qui ne devrait jamais être utilisé, juste pour que je puisse référencer un fichier plus profondément dans la hiérarchie.
Mise à jour
Je travaille avec un système de génération qui génère le __init__.py
est pour moi et applique la structure du répertoire et bien que je puisse jouer avec la hiérarchie, je préfère simplement ajouter le __init__.py
moi même. Pour changer légèrement la question, pourquoi ai-je besoin d'un package python à tous les niveaux au lieu de simplement en haut? Est-ce juste une règle selon laquelle vous ne pouvez importer que des modules à partir du python ou à partir d'une chaîne de paquets hors du chemin python?
Oui, ce fichier est requis si vous souhaitez que le répertoire soit traité comme module.
Les fichiers
__init__.py
Sont nécessaires pour que Python traite les répertoires comme contenant des packages; cela est fait pour empêcher les répertoires avec un nom commun, tel que chaîne, de masquer involontairement des modules valides qui se produire plus tard sur le chemin de recherche du module. Dans le cas le plus simple,__init__.py
peut simplement être un fichier vide, mais il peut également exécuter le code d'initialisation du package ou définir la variable__all__
, décrite plus loin.
https://docs.python.org/3/tutorial/modules.html#packages
J'essaie de créer un __init__.py
Non vide. Vous avez une grande possibilité de documenter le module, de vous débarrasser des importations imbriquées pour les utilisateurs/développeurs en fournissant les objets les plus utiles (classes/fonctions) au premier niveau ... ... pour être aussi simple à utiliser que possible dans contrairement à - disons - le Java importe
Modifier après la mise à jour de la question
Les importateurs/chercheurs par défaut (examinez le sys.meta_path
) Sont:
Le troisième est la chose __init__.py
(En fait FrozenImporter aussi).
PathFinder
recherche le module dans les chemins de sys.path
(Et dans __path__
Défini dans les packages). Le module peut être autonome python (s'il est à la racine du chemin recherché) ou répertoire avec __init__.py
.
En vous référant à votre exemple:
foo/
bar/
__init__.py
baz.py
Si vous créez _init__.py
Dans foo/
, foo.bar.baz
Sera disponible (comme vous l'avez dit).
Si vous ajoutez foo/
À sys.path
Ou le passez par PYTHONPATH=foo/
, bar.baz
Sera disponible (remarque sans module parent foo).
Si vous écrivez votre propre Finder (et Loader) vous pouvez par exemple charger n'importe quel fichier que vous voulez malgré où il se trouve. Cela vous donne un grand pouvoir. Par exemple, jetez un œil à stack-overflow-import
, expose le code basé sur les résultats de recherche de SO.