Ayant déjà utilisé des packages plats, je ne m'attendais pas au problème que j'ai rencontré avec les packages imbriqués. Voici…
Disposition du répertoire
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Contenu de init .py
Les deux package/__init__.py
et package/subpackage/__init__.py
sont vides.
Contenu de module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
Contenu de test.py
(3 versions)
Version 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
C'est la manière mauvaise et dangereuse d'importer des choses (tout importer en vrac), mais cela fonctionne.
Version 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Un moyen plus sûr d'importer, élément par élément, mais ça échoue, Python ne veut pas ça: échoue avec le message: "Aucun module nommé module". Pourtant …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
… Dit <module 'package.subpackage.module' from '...'>
. Donc c'est un module, mais ce n'est pas un module / -P 8-O ... euh
Version 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Celui-ci fonctionne. Donc, vous êtes soit obligé d'utiliser le préfixe overkill tout le temps, soit d'utiliser la méthode non sécurisée comme dans la version n ° 1 et interdite par Python d'utiliser la méthode sûre et pratique? La meilleure façon, qui est sûre et évite les longs préfixes inutiles, est la seule que Python rejette? Est-ce parce qu'il aime import *
ou parce qu'il aime les préfixes trop longs (ce qui n'aide pas à appliquer cette pratique)?.
Désolé pour les mots difficiles, mais cela fait deux jours que j'essaye de contourner ce comportement stupide. À moins que je ne me sois totalement trompé quelque part, cela me laissera le sentiment que quelque chose est vraiment cassé dans le modèle de paquetage et de sous-paquet de Python.
Remarques
- Je ne veux pas compter sur
sys.path
, pour éviter les effets secondaires globaux, ni sur les*.pth
fichiers, qui ne sont qu'une autre façon de jouersys.path
avec les mêmes effets globaux. Pour que la solution soit propre, elle doit être uniquement locale. Soit Python est capable de gérer les sous-packages, soit ce n'est pas le cas, mais il ne devrait pas nécessiter de jouer avec la configuration globale pour pouvoir gérer les choses locales. - J'ai aussi essayé d'utiliser les importations dans
package/subpackage/__init__.py
, mais ça n'a rien résolu, ça fait la même chose, et se plaintsubpackage
n'est pas un module connu, alors queprint subpackage
dit que c'est un module (comportement bizarre, encore une fois).
Peut-être que je me trompe complètement (l'option que je préférerais), mais cela me déçoit beaucoup de Python.
Un autre moyen connu à côté des trois que j'ai essayé? Quelque chose que je ne sais pas?
(soupir)
-----% <----- éditer ----->% -----
Conclusion jusqu'à présent (après les commentaires des gens)
Il n'y a rien de tel qu'un vrai sous-package en Python, car toutes les références de package vont uniquement vers un dictionnaire global, ce qui signifie qu'il n'y a pas de dictionnaire local, ce qui implique qu'il n'y a aucun moyen de gérer la référence de package locale.
Vous devez utiliser un préfixe complet ou un préfixe court ou un alias. Un péché:
Version du préfixe complet
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Version de préfixe court (mais préfixe répété)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
Ou bien, une variante de ce qui précède.
from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
Version factorisée
Si cela ne vous dérange pas d'importer plusieurs entités en même temps dans un lot, vous pouvez:
from package.subpackage.module import attribute1, attribute2
# and etc.
Pas dans mon premier goût préféré (je préfère avoir une déclaration d'importation par entité importée), mais c'est peut-être celle que je privilégierai personnellement.
Mise à jour (2012-09-14):
Enfin semble être OK dans la pratique, sauf avec un commentaire sur la mise en page. Au lieu de ce qui précède, j'ai utilisé:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.