Les Crash-Devs d'un Passionné

Import dynamique des modules python

/Catégorie/python

Temps de lecture : 2 minutes

Nous avons pour habitude d'importer les modules en haut de page de notre code python

import pytest

Mais dans certains cas il peut être intéressant de ne charger que les modules nécessaires surtout quand ces modules sont différents pendant l’exécution du programme.

Nous allons pouvoir utiliser le dunder import pour faire l'équivalent ci-dessus

__import__('pytest')

Sachant que la chaîne de caractère pytest peut provenir d'une variable assignée différemment en fonction de la logique de votre code.

Nous allons pouvoir utiliser sinon le module standard importlib avec import_module

clipboard
Copier le code
1
2
import importlib
module = importlib.import_module("file1")

Nous allons considérer que le module file1 contient

clipboard
Copier le code
1
2
3
4
class User():

    def __init__(self):
        self.name = "David"

Après avoir importé les modules, nous pouvons avoir besoin de créer une instance. Pour cela la fonction standard getattr() est ce qui nous permettra d'obtenir la référence de notre objet

klass = getattr(module, "User")

Il nous reste plus qu'à instancier notre classe

clipboard
Copier le code
1
2
3
print(klass) # <class 'other.file1.User'>
print(klass()) # <other.file1.User object at 0x7ff6ea62dee0>
print(klass().name) # David

L'intérêt d'utiliser cette méthode est valable surtout si le nom de l'instance est dynamique. Nous allons ici considérer que User provient d'un paramètre de notre script. Pour le récupérer nous allons utiliser

sys.argv[1]

N'oubliez pas de préciser le nom de votre classe en paramètre de votre commande

python3 file.py User

Si vous voulez importer votre module de manière relative, il faut ajouter un paramètre package avec le nom du dossier pour que l'import fonctionne

module = importlib.import_module(".file1", package="other")

Vous voyez que l'import des vos librairies en dynamique est largement abordable, voici l'exemple complet associé à la commande

python3 file_complet.py User

clipboard
Copier le code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import importlib 
module = importlib.import_module("file1")

sys = __import__('sys') # or import sys
class_name = sys.argv[1]

klass = getattr(module, class_name)

print(klass)         # <class 'other.file1.User'>
print(klass())       # <other.file1.User object at 0x7ff6ea62dee0>
print(klass().name)  # David