2010-07-13 5 views
0

Lors de l'exécution, le code Python obtient le nom d'un sous-module à charger, que je ne connaissais pas auparavant. Maintenant, je veux vérifier, si ce sous-module existe à l'intérieur d'un module existant. Considérez cette structure, où foo et bar peut préciser:Comment vérifier les sous-modules en Python avec hasattr

master/ 
| 
|- __init__.py 
| 
|- foo/ 
| | 
| |- __init__.py 
| 
|- bar/ 
    | 
    |- __init__.py 

Maintenant, d'habitude je le fais, qui travaille pour defs et variables:

import master 

unknown_submodule = "foo" 
if hasattr(master, unknown_submodule): 
    pass # all's well 

ou je suis attrapant le AttributeError, qui fonctionne également.

Cependant, avec la structure de fichier ci-dessus, je ne suis pas capable de mettre cette approche en place et de travailler. hasattr() renvoie toujours False (c'est-à-dire qu'il y a toujours un attribut AttributeError).

Si je regarde dir(master), je vois cette sortie:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__'] 

et même en spécifiant explicitement __all__ dans master/__init__.py ne vous aide pas, mais change le répertoire() pour

['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__'] 

Toute idée , ce que je fais mal, ou s'il y a un moyen de réaliser ce genre de tests? (BTW: Python 2.6 sur Win/Cygwin, si c'est de tout intérêt)

Répondre

2

Submodules ne sont pas des attributs de leurs modules parents, sauf mention explicite. Essayez simplement d'importer le module et attraper ImportError:

try: 
    __import__("os.peth", fromlist=[os]) 
except ImportError: 
    pass 
+0

Que voulez-vous dire par «déclaré explicitement»? Je pensais que c'était pour ça? Avez-vous un pointeur à portée de main pour une explication utile? (Autre que http://docs.python.org/tutorial/modules.html ou http://effbot.org/zone/import-confusion.htm) En dehors de cela, oui le '__import __()' fait ce qui est demandé. – Boldewyn

+1

Non, '__all__' détermine ce qui est importé quand vous dites' from ... import * '. Mais ce n'est pas lié à votre problème. Si vous avez un module 'A' et un module' A.B', l'importation de 'A' n'apporte pas magiquement un membre' B' à 'A'-seulement si' A' importe lui-même 'A.B'. Pour accéder à 'A.B', vous devez importer' A.B', pas 'A'. Dans le cas de 'os.path', l'importation de' os' fonctionne parce que 'os' importe activement' os.path'. – Philipp

+0

Merci pour l'explication! Je pense que je commence à avoir une emprise sur ce sujet. – Boldewyn

1

vous pouvez faire

try: 
import module.submodule 

except ImportError: 
    print 'failed or whatever' 
+0

Oui, cela fonctionne, merci. Cependant, savez-vous * pourquoi *? – Boldewyn

+0

Si 'master/__ init __. Py' n'importent pas activement' master.foo', alors 'master' n'a aucun membre appelé' foo'. Si vous venez d'importer 'master', alors' master.foo' soulève un 'AttributeError' indépendamment du fait que' master.foo' existe. – Philipp

1

J'ai eu récemment de vérifier l'existence de sous-module et depuis que je suis en utilisant python 3.4.1, je donne une nouvelle réponse à la question:

en python 3.4.1, vous pouvez utiliser importlib.util.find_spec(name, package=None) (https://docs.python.org/3.4/library/importlib.html#importlib.util.find_spec)

import importlib 
module_exists = importlib.util.find_spec('path.to.my.module') 

Aussi simple que ça =)

Questions connexes