2009-08-27 12 views
1

Désolé pour le titre générique, va changer une fois que je comprends la source de mon problème j'ai la structure suivante:problème avec python et __import__

foo/ 
foo/__init__.py 
foo/bar/ 
foo/bar/__init__.py 
foo/bar/some_module.py 

Lorsque je tente d'importer un_module en le faisant:

from foo.bar import some_module 

cela fonctionne comme un charme. Mais ce n'est pas bon pour moi, puisque je ne connais que le nom du module à importer en runtime. donc si j'essaye:

from foo.bar import * 
mod=__import__('some_module') 

Je reçois une erreur. Est-ce que je fais quelque chose de mal? Y a-t-il une meilleure manière de faire cela? et pourquoi cela se passe-t-il?

Pourquoi est-ce? Je ne suis pas sûr de comprendre complètement le concept derrière les paquets python. Je pensais qu'ils étaient équivalents aux paquets de java et donc

+3

Que dit le message d'erreur? – ewall

+2

votre 'some_module' est déjà importé! – SilentGhost

Répondre

7

je crois que la bonne façon de le faire est:

mod = __import__('foo.bar', fromlist = ['some_module']) 

De cette façon, même la partie « foo.bar » peut être changé lors de l'exécution. Par conséquent, some_module sera disponible en tant que mod.some_module; utiliser getattr si vous le voulez dans une variable séparée:

the_module = getattr(mod, 'some_module') 
0

De l'docs:

Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime.

Cependant, la notation en pointillés devrait fonctionner:

mod = __import__('foo.bar.some_module') 
1
from foo.bar import * 

est une mauvaise pratique car il importe some_module dans la portée globale.

Vous devriez être en mesure d'accéder à votre module via:

import foo.bar 
mod = getattr(foo.bar, 'some_module') 

Il peut être facilement démontré que cette approche fonctionne:

>>> import os.path 
>>> getattr(os.path, 'basename') 
<function basename at 0x00BBA468> 
>>> getattr(os.path, 'basename\n') 
Traceback (most recent call last): 
    File "<pyshell#31>", line 1, in <module> 
    getattr(os.path, 'basename\n') 
AttributeError: 'module' object has no attribute 'basename 
' 

post-scriptum Si vous êtes toujours intéressé par l'utilisation de votre type de déclaration d'importation. Vous avez besoin d'un eval:

from foo.bar import * 
eval('some_module') 

Pour clarifier: non seulement il est une mauvaise pratique d'utiliser * -import il est encore pire en combinaison avec eval. Il suffit donc d'utiliser getattr, il est conçu exactement pour des situations comme la vôtre.

+0

-1 pour recommander eval(). Toujours utiliser globals() ['some_module'] à la place si tout ce que vous voulez est de rechercher la valeur de la portée globale. –

+0

Très bien, encore une fois pour votre clarification. getattr() est la bonne réponse ici. Si vous devez utiliser __import __(), consultez la réponse de kurczak. –

+0

Euh oh, maintenant je reçois "Vote trop vieux pour être changé, sauf si cette réponse est éditée".Mes excuses - j'ai vu eval() dans un bloc de code et j'ai cliqué automatiquement sur -1. –