2010-06-12 6 views
2

I ont une structure de répertoire:importations Python par le module de dossier

example.py 
templates/ 
    __init__.py 
    a.py 
    b.py 

a.py et b.py ont une seule classe, le même nom que le fichier (parce qu'ils sont des modèles de guépard). Pour des raisons purement style, je veux être en mesure d'importer et d'utiliser ces classes dans example.py comme ceci:

import templates 

t = templates.a() 

En ce moment je fais cela en ayant cela dans le du dossier modèle __init__.py:

__all__ = ["a", "b"] 
from . import * 

Cependant , cela semble assez pauvre (et peut-être superflu), et ne même pas faire ce que je veux, comme je dois utiliser les classes comme ceci:

t = templates.a.a() 

pensées?

Répondre

4

Pour éviter de répéter from <whatever> import * 25 fois, vous avez besoin d'une boucle, tel que:

import sys 

def _allimports(modnames) 
    thismod = sys.modules[__name__] 

    for modname in modnames: 
    submodname = '%s.%s' % (thismod, modname) 
    __import__(submodname) 
    submod = sys.modules[submodname] 
    thismod.__dict__.update(submod.__dict__) 

_allimports('a b c d e'.split()) # or whatever 

Je place le code significatif dans une fonction parce que (a) c'est toujours mieux [[pour la performance et éviter de polluer l'espace de nom du module]], (b) dans ce cas particulier, il évite aussi les accidents (par ex. un nom thismod ou modnames ... donc il est important de garder les noms que nous utilisons dans la boucle locale à la fonction, pas globals de module, donc ils ne peuvent pas être accidentellement piétinés ;-).

Si vous souhaitez appliquer le fait qu'un module nommé modname ne possède qu'une seule classe (ou autre global) avec le même nom, changer la dernière instruction de la boucle:

setattr(thismod, modname, getattr(submod, modname)) 
+0

merci! des pensées sur si ce que j'essaye de faire/ce que j'ai maintenant est une bonne idée du tout? – colinmarc

+0

@colinmarc, J'approuve votre scepticisme quant à l'utilisation d'une telle introspection (profonde)/(légère) métaprogrammation dans le code de production, mais vous n'avez pas vraiment d'alternative ici - les fichiers 'a.py' & c avec classe 'a' sont (je crois) un guépard donné, et demander aux utilisateurs de toujours faire' à partir de modèles importer un '(& c) puis utiliser' aa() '(& c) se sent quelque peu redondant (je pourrais y aller, mais seulement parce que je suis un évangéliste pour "toujours importer un ** module ** - ** jamais ** un paquet, ** jamais ** rien de _inside_ un module" et un ennemi juré de 'import *' ...; -) - la plupart des gens sont plus raisonnables! -) –

+0

@colinmarc, bien sûr, si vous pouvez avoir toutes les classes dans un 'template.py' à la place du répertoire/template' template' actuel, ce sera beaucoup plus simple. –

3

Dans votre __init__.py:

from a import * 
from b import * 

Maintenant tous a 's contenu sera en templates, tout comme tous b' s contenu.

+0

est-il un moyen de faire ceci sans ligne pour chacun? J'ai vraiment comme 25 modèles – colinmarc

+0

Je suis un fan de la simplicité. Cela ne me dérangerait pas d'ajouter une ligne à __init__.py chaque fois que j'ajouterais un autre module. Votre goût peut différer ... –

3

Je ne savais même pas que vous pouviez avoir from . import *. Mon interpréteur Python se plaint de ces déclarations. Pourtant, à votre problème, vous pouvez faire:

# __init__.py 
from . import a, b 
a = a.a 
b = a.b 

vous pouvez maintenant utiliser

# example.py 
import templates 
t = templates.a() 

autre solution:

# __init__.py 
from a import * 
from b import * 
+1

"from.import ..." est une importation relative, ce qui n'est généralement pas une très bonne idée. –

Questions connexes