J'écris une application Python qui prend comme commande un argument, par exemple:
$ python myapp.py command1
Je veux que l'application soit extensible, c'est-à-dire qu'elle puisse 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 souhaite 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 une fonction __import__ , qui prend une chaîne pour un nom de module:
__import __ (nom, globaux = Aucun, locaux = Aucun, fromlist = (), niveau = 0)
La fonction importe le nom du module, en utilisant potentiellement les valeurs globales et locales données pour déterminer comment interpréter le nom dans un contexte de package. La fromlist donne les noms des objets ou sous-modules qui doivent être importés du module donné par 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 très bien, je me demande simplement s'il existe un moyen plus idiomatique d'accomplir ce que nous faisons avec ce code.
Notez que je ne veux pas spécifiquement utiliser 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é.
dir(__import__)
. La fromlist doit être une liste de noms à émuler "from import name ...".
importlib
: stackoverflow.com/a/54956419/687896