J'utilise Python 3.5.1. J'ai lu le document et la section package ici: https://docs.python.org/3/tutorial/modules.html#packages
Maintenant, j'ai la structure suivante:
/home/wujek/Playground/a/b/module.py
module.py
:
class Foo:
def __init__(self):
print('initializing Foo')
Maintenant, pendant que vous êtes /home/wujek/Playground
:
~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>
De même, maintenant à la maison, superfolder de Playground
:
~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>
En fait, je peux faire toutes sortes de choses:
~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b
Pourquoi ça marche? Je pensais qu'il devait y avoir des __init__.py
fichiers (des fichiers vides fonctionneraient) dans les deux a
et b
pour module.py
être importables lorsque le chemin Python pointe vers le Playground
dossier?
Cela semble avoir changé depuis Python 2.7:
~ $ PYTHONPATH=Playground python
>>> import a
ImportError: No module named a
>>> import a.b
ImportError: No module named a.b
>>> import a.b.module
ImportError: No module named a.b.module
Avec les __init__.py
deux ~/Playground/a
et ~/Playground/a/b
cela fonctionne très bien.
la source
Zen Of Python
ligne 2:Explicit is better than implicit.
....__init__.py
, parfois non. Dans Python 3, lorsque j'ai besoin de ces éléments, je crée un nouveau__init__.py
avec un code spécifique, sinon je n'en ai pas. Cela est pratique pour savoir visuellement quels packages ont un init personnalisé. Au lieu de cela, dans python 2, je dois toujours placer un__init__.py
(souvent vide), ce qui en fait un grand nombre et finalement plus difficile de me souvenir où vous avez placé votre code d'initialisation. Cela devrait également correspondre à "Il devrait y avoir une - et de préférence une seule - façon évidente de le faire.".IMPORTANT
La réponse de @ Mike est correcte mais trop imprécise. Il est vrai que Python 3.3+ prend en charge les packages d'espace de noms implicites qui lui permettent de créer un package sans
__init__.py
fichier.Cependant, ceci s'applique UNIQUEMENT aux fichiers VIDE
__init__.py
. Les fichiers VIDE__init__.py
ne sont donc plus nécessaires et peuvent être omis. Si vous souhaitez exécuter un script d'initialisation particulier lorsque le package ou l'un de ses modules ou sous-packages sont importés, vous avez toujours besoin d'un__init__.py
fichier. C'est une excellente réponse à Stack Overflow pour expliquer pourquoi vous voudriez utiliser un__init__.py
fichier pour effectuer une initialisation supplémentaire au cas où vous vous demandez pourquoi cela est utile.Exemple de structure de répertoire:
parent_package/child_package/__init__.py
:EXEMPLES
Les exemples ci-dessous montrent comment le script d'initialisation est exécuté lorsque le
child_package
ou l'un de ses modules est importé.Exemple 1 :
Exemple 2 :
la source
run_script.py
dans le même répertoire queparent_package
, puis-je importer commefrom parent_package.child_package import child1
sans__init__.py
?child1.py
,child2.py
au lieu de simplement mettre leur code ensemble dans__init__
.py directement.__init__
être des importations relatives, par exemplefrom . import child1
? L'importation absolue me donneModuleNotFoundError
(en Python 3.6)__init__.py
est encore parfois nécessaire, comme lorsque vous voulez faire référence à un sous-dossier en tant que package. Par exemple, si je l'exécute,python -m test.foo
cela ne fonctionnait pas jusqu'à ce que j'aie créé un vide__init__.py
sous le dossier de test. Et je parle de la version 3.6.6 ici!Si vous en avez
setup.py
dans votre projet et que vous l'utilisezfind_packages()
, il est nécessaire d'avoir un__init__.py
fichier dans chaque répertoire pour que les packages soient automatiquement trouvés.UPD : Si vous souhaitez utiliser des packages d'espace de noms implicites sans
__init__.py
avoir à utiliser à lafind_namespace_packages()
placeDocs
la source
Je dirais que l'on devrait omettre le
__init__.py
seul si l'on veut avoir le package d'espace de noms implicite . Si vous ne savez pas ce que cela signifie, vous ne le voulez probablement pas et vous devriez donc continuer à utiliser le__init__.py
même en Python 3.la source