Comment importer un module donné son nom?
Je suis en train d'écrire une application Python qui prend comme une commande comme argument, par exemple:
$ python myapp.py command1
Je veux la demande pour être extensible, qui est, pour être en mesure d'ajouter de nouveaux modules qui implémentent de nouvelles commandes sans avoir à changer la source principale de l'application. L'arbre ressemble à quelque chose comme:
myapp/
__init__.py
commands/
__init__.py
command1.py
command2.py
foo.py
bar.py
Je veux donc l'application pour trouver la disposition des modules de commande lors de l'exécution et exécutez-la.
Python définit un __import__ fonction qui prend une chaîne de caractères pour un nom de module:
__import__(nom, globals=None, les habitants=None, fromlist=(), niveau=0)
Les importations de fonction le nom du module, éventuellement en utilisant le compte tenu de variables globales et locales afin de déterminer comment interpréter le nom dans un package contexte. Le fromlist donne les noms des objets ou des submodules qui doivent être importées à partir du module donné par son nom.
Source: https://docs.python.org/3/library/functions.html#import
Donc actuellement, j'ai quelque chose comme:
command = sys.argv[1]
try:
command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
# Display error message
command_module.run()
Cela fonctionne bien, je me demandais simplement si il est peut-être un plus idiomatiques façon d'accomplir ce que nous faisons avec ce code.
Remarque que j'ai spécifiquement ne voulez pas d'obtenir à l'aide des œufs ou des points d'extension. Ce n'est pas un projet open-source et je n'ai pas s'attendre à être "plugins". Le point est de simplifier le code de l'application principale et de supprimer la nécessité de le modifier à chaque fois qu'un nouveau module de commande est ajouté.
- Ce qui ne l'fromlist=["myapp.les commandes"] faire?
- en python, shell, tapez ceci:
dir(__import__)
. Le fromlist doit être une liste de noms pour émuler "de nom" importer ...". - module d'Importation de variable de chaîne
- À compter de 2019, vous devriez regarder pour des
importlib
: stackoverflow.com/a/54956419/687896
Vous devez vous connecter pour publier un commentaire.
Avec Python âgés de plus de 2.7/3.1, c'est à peu près la façon dont vous le faites.
Pour les versions plus récentes, voir
importlib.import_module
pour Python 2 et et Python 3.Vous pouvez utiliser
exec
si vous voulez ainsi.Ou à l'aide de
__import__
vous pouvez importer une liste de modules en faisant ceci:Déchiré directement à partir de Dive Into Python.
__init__
de ce module?__import__
. Le 2.7 docs: "Parce que cette fonction est destinée à être utilisée par l'interpréteur Python, et non pour un usage général, il est préférable d'utiliser importlib.import_module()..." Lors de l'utilisation de python3, leimp
module permet de résoudre ce problème, comme monkut mentionne ci-dessous.foreach
siforeach
lorsque vous avezfor element in
etmap()
bien 🙂La méthode recommandée pour Python 2.7 et 3.1 et plus tard est d'utiliser
importlib
module:par exemple
__import__
fonction en faveur de l'mentionnés ci-dessus module.os.path
; commentfrom os.path import *
?globals().update(my_module.__dict)
Comme mentionné la imp module vous fournit des fonctions de chargement:
Je les ai utilisées avant d'effectuer quelque chose de similaire.
Dans mon cas, j'ai défini une classe spécifique, avec des méthodes qui ont été nécessaires.
Une fois, j'ai chargé le module, je voudrais vérifier si la classe était dans le module, puis de créer une instance de cette classe, quelque chose comme ceci:
expected_class
de sorte que vous pourriez faireclass_inst = getattr(py_mod,expected_name)()
à la place.Utiliser le pgi module, ou la plus directe
__import__()
fonction.Si vous le voulez dans vos locaux:
même serait de travailler avec
globals()
Vous pouvez utiliser
exec
:as command_module
à la fin de l'instruction d'importation et puis necommand_module.run()
Aujourd'hui, vous devez utiliser importlib.
Importer un fichier source
La docs fait donner une recette pour ça, et il va comme:
Importer un package
De l'importation d'un package (par exemple,
pluginX/__init__.py
) sous le répertoire courant est en fait simple:sys.modules[module_name] = module
à la fin de votre code si vous voulez être en mesure deimport module_name
par la suiteSimilaires comme @monkut 's solution, mais réutilisables et tolérante des erreurs décrites ici http://stamat.wordpress.com/dynamic-module-import-in-python/:
Qu'il semble que vous voulez vraiment est une architecture de plugin.
Vous devriez jeter un oeil à la les points d'entrée fonctionnalités fournies par le setuptools paquet. Il offre un excellent moyen de découvrir les plugins qui sont chargés pour votre application.
ex: mon module noms sont comme des jan_module/feb_module/mar_module
Le dessous de la pièce a fonctionné pour moi:
si vous souhaitez importer dans un shell-script:
La suite fonctionné pour moi:
Il charge les modules du dossier 'mode'. Les modules ont une classe unique avec le même nom que le nom du module. E. g. le fichier modus/modu1.py contient:
Le résultat est une liste de chargement dynamique des classes "cartes".
fl
? La boucle de définition est trop complexe. Le chemin est codé en dur (et pour un exemple, pas d'importance). C'est à l'aide de décourager python (__import__
), ce qui est tout ce quifl[i]
des trucs? Fondamentalement c'est illisible, et est inutilement complexe pour quelque chose qui n'est pas si difficile - voir le haut voté réponse avec son one-liner.