Python >> Tutoriel Python >  >> Python

Fonction __import__() de Python - Importation dynamique d'une bibliothèque par nom

La fonction "dunder" intégrée de Python __import__() vous permet d'importer une bibliothèque par son nom . Par exemple, vous souhaiterez peut-être importer une bibliothèque qui a été fournie en tant qu'entrée utilisateur, de sorte que vous n'ayez peut-être que le nom de chaîne de la bibliothèque. Par exemple, pour importer dynamiquement la bibliothèque NumPy, vous pouvez exécuter __import__('numpy') .

Dans ce tutoriel, je vais vous montrer comment utiliser le __import__() pour personnaliser le comportement d'importation de votre programme Python et importer un module par nom (chaîne). C'est une fonction puissante qui ne devrait être utilisée que par des codeurs avancés. Mais le fait que vous lisiez ceci montre déjà que vous savez ce que vous faites. Alors, passons à autre chose pour en savoir plus sur cette astuce Python !

Notez qu'il est généralement recommandé d'utiliser le importlib module si votre seul objectif est d'importer un module par son nom.

Exemple d'utilisation __import__()

Le code suivant vous montre comment utiliser la fonction intégrée __import__() pour importer la bibliothèque NumPy et lui attribuer le nom numpy . C'est sémantiquement équivalent à écrire import numpy .

numpy = __import__('numpy', globals(), locals(), [], 0)
# Semantically equivalent to: import numpy

a = numpy.array([1, 2, 3])
print(a * 2)
# [2 4 6]

Syntaxe __import__()

__import__(name, globals=None, locals=None, fromlist=(), level=0)
Argument : name chaîne. Nom de la bibliothèque à importer.
Argument : globals=None dictionnaire. Optionnel. Un dictionnaire de name: objec t mappages qui définissent les noms dans le contexte d'importation. Par exemple, cela peut être le résultat du globals() si vous souhaitez utiliser votre contexte global actuel.
Argument : locals=None dictionnaire. Optionnel. Un dictionnaire de name: object mappages qui définissent les noms dans le contexte d'importation. Par exemple, cela peut être le résultat du locals() si vous souhaitez utiliser votre contexte local actuel.
Argument : fromlist=() itérable. Optionnel. Vous permet d'importer uniquement des objets spécifiques plutôt que le module entier.
Argument : level=0 entier. Optionnel. Utilisez des importations absolues ou relatives.
-1 —> La valeur par défaut est -1 indiquant que les importations absolues et relatives seront tentées.
0 —> Importations absolues uniquement
x>0 —> Rechercher x répertoires parents relatifs au module appelant __import__() .
Valeur de retour object L'objet module importé.

Pourquoi __import__() est-il déconseillé ?

Si vous utilisez l'instruction d'importation comme dans import numpy , il utilise en interne la fonction intégrée __import__() comme implémentation sous-jacente sémantiquement plus puissante.

Vous pouvez remplacer ce comportement et le personnaliser selon vos besoins en implémentant vous-même la fonction __import__(). Cependant, vous ne devriez pas le faire car cela peut provoquer des effets secondaires dangereux. Par exemple, le document PEP 302 déconseille explicitement de le faire. Vous pouvez demander :pourquoi ?

Pourquoi __import__() déconseillé selon PEP 302 ?

Écraser le __import__() fonction pose trois problèmes :

  • Vous devez réimplémenter le mécanisme d'importation. Mais vous ne voudrez peut-être changer qu'une petite chose.
  • Il a une sémantique et des responsabilités complexes. Il peut injecter de nouvelles sources de bogues dans votre code.
  • Même les modules système en sys.modules appeler le __import__() . Donc, si vous l'écrasez, vous altérez un code global bien testé.

Au lieu de cela, la PEP 302 conseille d'utiliser des hooks d'importation plus simples . Vous pouvez demander :

Que sont les crochets d'importation ?

Ils constituent un moyen plus propre d'importer dynamiquement des bibliothèques, compte tenu de leur nom (et, éventuellement, de leur chemin). Voici les parties pertinentes de la PEP 302 :


— commencer la source PEP 302 —

Le protocole implique deux objets :un finder et un chargeur . Un objet finder a une seule méthode :

finder.find_module(fullname, path=None)

Cette méthode sera appelée avec le nom complet du module. Si le finder est installé sur sys.meta_path , il recevra un deuxième argument, qui est None pour un module de niveau supérieur, ou package.__path__ pour les sous-modules ou sous-packages. Il doit renvoyer un objet chargeur si le module a été trouvé, ou None si ce n'était pas le cas. Si find_module() déclenche une exception, elle sera propagée à l'appelant, annulant l'importation.

Un objet chargeur a également une méthode :

loader.load_module(fullname)

Cette méthode renvoie le module chargé ou lève une exception, de préférence ImportError si une exception existante n'est pas propagée. Si load_module() est invité à charger un module qu'il ne peut pas, ImportError doit être augmenté.

— source finale PEP 302 —


Il s'avère que la bibliothèque importlib.import_module() implémente ce dont vous avez besoin - et vous devriez l'utiliser à la place du __import__() fonction.

Résumé

Fonction "dunder" intégrée de Python __import__() vous permet d'importer une bibliothèque par son nom, si vous n'avez accès qu'au nom de la bibliothèque sous forme de chaîne.

Par exemple, vous souhaiterez peut-être importer une bibliothèque qui a été fournie en tant qu'entrée utilisateur. Par exemple, pour importer dynamiquement la bibliothèque NumPy, vous pouvez exécuter __import__('numpy') .

numpy = __import__('numpy', globals(), locals(), [], 0)
# Semantically equivalent to: import numpy

a = numpy.array([1, 2, 3])
print(a * 2)
# [2 4 6]

Le __import__() fonction n'est pas recommandée. Si vous devez importer des bibliothèques par nom, la méthode recommandée consiste à utiliser le importlib bibliothèque.


Voulez-vous améliorer vos compétences Python d'une manière amusante et facile à consommer ? Considérez les ressources suivantes et devenez un maître codeur !