J'écris une application Python qui prend une commande comme argument, par exemple :
$ python myapp.py command1
Je souhaite que l'application soit extensible, c'est-à-dire qu'il soit possible d'ajouter de nouveaux modules qui mettent en œuvre de nouvelles commandes sans devoir modifier 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 que l'application trouve les modules de commande disponibles au moment de l'exécution et exécute le module approprié.
Python définit un __import__()
qui prend une chaîne de caractères pour le nom du module :
__import__(name, globals=None, locals=None, fromlist=(), level=0)
La fonction importe le module
name
en utilisant potentiellement lesglobals
ylocals
pour déterminer comment interpréter le nom dans un contexte de paquetage. L'adressefromlist
donne les noms des objets ou des sous-modules qui doivent être importés du module donné parname
.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 très bien, mais je me demande s'il n'y a pas une façon plus idiomatique d'accomplir ce que nous faisons avec ce code.
Notez que je ne veux surtout pas entrer dans l'utilisation des œufs ou des points d'extension. Ce n'est pas un projet open-source et je ne m'attends pas à ce qu'il y ait des "plugins". Le but 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é.
0 votes
À quoi sert l'option fromlist=["myapp.commands"] ?
2 votes
@PieterMüller : dans un shell python, tapez ceci :
dir(__import__)
. La fromlist doit être une liste de noms pour émuler "from name import ...".4 votes
Importer un module à partir d'une variable de type chaîne
1 votes
À partir de 2019, vous devrez rechercher
importlib
: stackoverflow.com/a/54956419/6878960 votes
Ne pas utiliser __import__ voir Doc Python utiliser un importlib.import_module