La question ici posé est comment importer dynamiquement un/des module(s) (sans en connaître le nom ni même savoir si il existe) et comment exécuter des fonctions contenus dans ces modules.
Cette méthode peut être utile si par exemple vous souhaitez faire un système de plugins. Cet article est une piste à explorer et aucunement une réponse complète !
Je n'ai pas la prétention de tout connaître en python, au contraire je pense plutot être un grand débutant dans ce langage, donc si quelqu'un se rend compte que je dis de la merde, qu'il n'hésite pas à me corriger.
Cette solution a été testé avec Python 2.5 et 2.6. Cela dit, si vous utilisez la version 2.6 il vous faudra ce bout de code piqué ici pour que ça marche (cette version corrige un bug). Ça nous permettra d'importer un module à la volée proprement.
# plugins.py
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()
Ensuite, le contenu d'un module. Pour des raisons de simplicité, je pars de l'idée que chaque module aura toujours une fonction du même nom dont le but sera d'appeler comme elle le souhaite les autres fonctions, et de se répartir le travail à exécuter à sa manière.
Faisons un exemple bidon mais simple : une fonction qui reçoit un texte et retourne un tableau de toutes les lignes.
# parselines.py
def start(**args):
data = []
for line in args['text'].split('\n'):
data.append(line)
return data
Bien, passons maintenant au vrai sujet de cet article : importer des modules et exécuter une fonction contenu dans ces modules. Encore une fois je donne un exemple simple et inutile, où l'on importe ce qui se trouve dans le dossier plugin/, pas de vérifications ni rien du tout.
#plugins.py
from os import listdir
data = []
args = {'text': 'Ligne une\nLigne deux\nLigne trois'}
for dirname in listdir('plugins/'):
# path sous la forme 'plugins/module_name/module_name'
pathname = 'plugins/' + dirname + '/' + dirname)
# Import
module = __import__(pathname)
# Appel de la fonction 'start' dans le module module avec args en arguments
data.append(getattr(module, 'start')(**args))
return data
getattr s'utilise comme ceci :
getattr(object, function_name)([arg])
object : le module
function_name : la fonction à importer
arg : arguments à donner à manger à la fonction (optionnel)
Voir 4.7.4. Unpacking Argument Lists pour avoir des arguments optionnels.
À vous de trouver comment gérer plusieurs plugins avec des fonctions et des arguments de fonctions différents entre chaque appel.
Ça donnera peut être suite à un second article plus complet sur la question, car je suis justement en train de tester un système un peu similaire pour les futurs plugins de Pblog 2.
0