Le fichier __init__.py ne sert pas qu’à déclarer un dossier comme un package importable. C’est aussi le code exécuté automatiquement, une seule fois, quand on importe le module.
Du coup vous pouvez mettre dedans tout code Python que vous souhaitez lancer à l’import. On y voit souvent :
- Initialisation du cache.
- Constantes comme
__version__
. - Import d’autres modules pour les mettre dans l’espace de nom courant.
- Check de dépendances.
- Aliasing.
- Monkey patching and hacks tout moches qui sont là temporairement pour 6 ans.
Je vous déconseille de mettre trop de code dans le fichier __init__.py, notamment du code métier. C’est une mauvaise habitude que l’on peut voir dans le code de Django par exemple. Car ça veut dire que l’import du package déclenche ce code, qui lui-même importe d’autres modules, qui déclenche d’autres codes, etc. Cela donne des effets de bord à l’import, alors que l’import d’un simple package est quelque chose que l’on veut généralement ne pas avoir beaucoup d’effets.
Dans Django par exemple, c’est ce qui fait que beaucoup de modules lèvent une exception à l’import :
django.core.exceptions.ImproperlyConfigured: Requested setting X but settings are not configured.
Alors qu’ils n’ont pas du tout besoin des settings pour fonctionner.
Si vous avez besoin que votre classe Bidule
soit directement importable dans votre package machin
, faites dans machin/__init__.py :
from .module_qui_contient_bidule import Bidule |
Du coup vous pourrez faire n’importe où ailleurs:
from machin import Bidule |
C’est bien plus propre que de mettre tout le code de Bidule
dans le __init__.py.
Et je reviens aussi avec mes fichiers .pth
Vous pouvez aussi y mettre du code qui s’exécute automatiquement:
Dans un fichier truc.pth:
import sys; exec(''.join(f) if __name__ == 'site' else '', {})
if vous(voulez):
vous pouvez exécuter n'importe quoi ici ici
avec Django je me sers des __init__.py dans ds dossier models, forms’pour avoir des modèles distincts par service.c’est une connerie ?
J’ai pas compris foxmask. Poste une arbo et le contenu des fichiers.
Globalement ça sert à exposer l’api publique d’un projet. En tout cas c’est comme ça que je l’utilise :)
Sinon c’est quoi l’Aliasing dans ce contexte ?
Par exemple :
Ce qui permet de faire des versions de transition quand on fait du deprecated.
J’ai eu un instant d’incompréhension aussi : c’est aliasing comme un alias, pas comme le lissage des bordures dans les affichages 3D.
Ca peut servir aussi pour éviter les
from bidule.machin import Machin
en ayant uniquementfrom bidule import Machin
(avecfrom .machin import Machin
dans le__init__.py
).@sam
je n’ai pas de forms.py ni de models.py mais un dossier forms et un dossier models et j’ai mis dans le __init__.py de chacun, ce qui est commun à toute mon appli.
donc partant de ton commentaire :
> Je vous déconseille de mettre trop de code dans le fichier __init__.py, notamment du code métier.
je me demandais si j’avais bien fait de le faire comme ça.
Nan, c’est pas une bonne idée. Met ça dans un fichier base.py et importe juste le nécessaire dans __init__ sinon un jour quelqu’un va vouloir importer forms.un_truc, et ça va lancer le code du __init__ alors que lui il voulait juste un_truc.
cool merci !
Très cool! Merci.
Hello,
L’ordre des import dans
__init__.py
peut-il avoir une importance ?Dans certains cas j’ai des erreurs dans mon code, je ne comprends pas très bien pourquoi.
Oui, puisque les imports exécutes le code des modules importés.