Exécuter scripts à partir du milieu d'un paquet est une mauvaise idée, pour un certain nombre de raisons, dont la plus évidente est celle que vous rencontrez : Lorsque vous import generator.the_generator
quelque part, generator
finit par être un paquet, donc une importation absolue de generator.the_page
ou une importation relative, fonctionnera parfaitement. Mais lorsque vous exécutez simplement le script generator/the_generator.py
il n'y a pas de generator.the_generator
juste __main__
et il n'y a pas de generator
paquet. La seule autre façon dont Python pourrait savoir comment trouver generator.the_page
serait si le répertoire parent de generator
étaient sur sys.path
ce qui n'est pas le cas.
Comme vous pouvez le deviner, vous peut contourner ce problème en brossant sys.path
pour y mettre le répertoire parent approprié mais c'est aussi une mauvaise idée.
Cette solution présente également de nombreux autres problèmes. Plus sérieusement, elle peut très facilement conduire à ce que le même module soit importé deux fois (car Python n'a aucun moyen de savoir que deux noms apparemment sans rapport se trouvent faire référence au même module). Elle est également difficile à déployer (vous ne pouvez pas installer un script à /usr/local/bin
s'il dépend de l'intérieur d'un paquet ), il ne fonctionnera pas si votre paquet est extrait d'un .zip ou d'un .egg, etc.
Il existe deux façons standard de résoudre ce problème.
Tout d'abord, il suffit d'exécuter le script comme un module plutôt que comme un script. Depuis le répertoire parent de generator
juste python -m generator.the_generator
au lieu de python generator/the_generator.py
.
L'un des principaux avantages de cette méthode est qu'elle fonctionne tout aussi bien dans les déploiements installés normaux, lorsque generator
est dans les paquets du site quelque part, comme dans testing.
Alternativement, créez un script qui se trouve à côté de generator
et lancez-la, pas un module à l'intérieur. Cela peut être aussi trivial que de déplacer tous les modules de la section if __name__ == '__main__':
code dans the_generator.py
en une fonction, puis en écrivant un wrapper de deux lignes :
import generator.the_generator
generator.the_generator.main()
Encore une fois, cela fonctionne tout aussi bien dans les déploiements installés normaux. De plus, cela signifie que le script peut être installé dans votre système de gestion de l'information. bin
ce qui rend les choses encore plus faciles, tout comme pip
o ipython
.