Maison développement back-end Tutoriel Python Différentes façons de corriger les importations circulaires en Python

Différentes façons de corriger les importations circulaires en Python

Nov 05, 2024 am 02:21 AM

Avez-vous déjà rencontré des importations circulaires en Python ? Eh bien, c'est une odeur de code très courante qui indique que quelque chose ne va pas avec la conception ou la structure.

Exemple d'importation circulaire

Comment se produit l'importation circulaire ? Cette erreur d'importation se produit généralement lorsque deux modules ou plus dépendant les uns des autres tentent d'importer avant de s'initialiser complètement.

Disons que nous avons deux modules : module_1.py et module_2.py.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()
Copier après la connexion
Copier après la connexion
Copier après la connexion
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans les extraits de code ci-dessus, module_1 et module_2 dépendent mutuellement l'un de l'autre.

L'initialisation de mody_obj dans module_1 dépend du module_2 et l'initialisation de modx_obj dans module_2 dépend du module_1.

C'est ce que nous appelons une dépendance circulaire. Les deux modules resteront bloqués dans les boucles d'importation lors de la tentative de chargement mutuel.

Si nous exécutons module_1.py, nous obtiendrons le traçage suivant.

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette erreur explique la situation de l'importation circulaire. Lorsque le programme a tenté d'importer ModY depuis module_2, à ce moment-là, module_2 n'était pas complètement initialisé (en raison d'une autre instruction d'importation qui tente d'importer ModX depuis module_1).

Comment réparer les importations circulaires en Python ? Il existe différentes façons de se débarrasser des importations circulaires en Python.

Corriger les importations circulaires en Python

Déplacer le code dans un fichier commun

Nous pouvons déplacer le code dans un fichier commun pour éviter les erreurs d'importation, puis essayer d'importer les modules à partir de ce fichier.

# main.py ----> common file
class ModX:
    pass

class ModY:
    pass
Copier après la connexion
Copier après la connexion

Dans l'extrait de code ci-dessus, nous avons déplacé les classes ModX et ModY dans un fichier commun (main.py).

# module_1.py
from main import ModY

class Mod_X:
    mody_obj = ModY()
Copier après la connexion
Copier après la connexion
# module_2.py
from main import ModX

class Mod_Y:
    modx_obj = ModX()
Copier après la connexion
Copier après la connexion

Maintenant, module_1 et module_2 importent les classes de main, ce qui corrige la situation d'importation circulaire.

Il y a un problème avec cette approche, parfois la base de code est si volumineuse qu'il devient risqué de déplacer le code dans un autre fichier.

Déplacer l'import à la fin du module

On peut décaler l'instruction import à la fin du module. Cela donnera le temps d'initialiser complètement le module avant d'importer un autre module.

# module_1.py
class ModX:
   pass

from module_2 import ModY

class Mod_X:
   mody_obj = ModY()
Copier après la connexion
Copier après la connexion
# module_2.py
class ModY:
   pass

from module_1 import ModX
Copier après la connexion
Copier après la connexion

Module d'importation dans la portée de la classe/fonction

L'importation de modules dans la portée de la classe ou de la fonction peut éviter les importations circulaires. Cela permet au module d'être importé uniquement lorsque la classe ou la fonction est invoquée. C'est pertinent lorsque nous voulons minimiser l'utilisation de la mémoire.

# module_1.py
class ModX:
  pass

class Mod_X:
   from module_2 import ModY
   mody_obj = ModY()
Copier après la connexion
Copier après la connexion
# module_2.py
class ModY:
   pass

class Mod_Y:
   from module_1 import ModX
   modx_obj = ModX()
Copier après la connexion
Copier après la connexion

Nous avons déplacé les instructions d'importation dans les classes Mod_X et Mod_Y respectivement dans module_1 et module_2.

Si nous exécutons module_1 ou module_2, nous n'obtiendrons pas d'erreur d'importation circulaire. Mais cette approche rend la classe accessible uniquement dans la portée de la classe, nous ne pouvons donc pas exploiter l’importation globalement.

Utilisation du nom/alias du module

Utiliser le nom du module ou simplement un alias comme celui-ci résout le problème. Cela permet aux deux modules de se charger complètement en différant la dépendance circulaire jusqu'à l'exécution.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()
Copier après la connexion
Copier après la connexion
Copier après la connexion
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()
Copier après la connexion
Copier après la connexion
Copier après la connexion

Utilisation de la bibliothèque importlib

On peut également utiliser la bibliothèque importlib pour importer les modules dynamiquement.

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
Copier après la connexion
Copier après la connexion
Copier après la connexion
# main.py ----> common file
class ModX:
    pass

class ModY:
    pass
Copier après la connexion
Copier après la connexion

Importations circulaires dans les packages Python

Habituellement, les importations circulaires proviennent de modules au sein du même package. Dans les projets complexes, la structure des répertoires est également complexe, avec des packages dans les packages.

Ces packages et sous-packages contiennent des fichiers __init__.py pour faciliter l'accès aux modules. C'est là que surgissent parfois involontairement des dépendances circulaires entre les modules.

Nous avons la structure de répertoires suivante.

# module_1.py
from main import ModY

class Mod_X:
    mody_obj = ModY()
Copier après la connexion
Copier après la connexion

Nous avons un package mainpkg et un fichier main.py. Nous avons deux sous-packages modpkg_x et modpkg_y dans mainpkg.

Voici à quoi ressemble chaque fichier Python dans modpkg_x et modpkg_y.

mainpkg/modpkg_x/__init__.py

# module_2.py
from main import ModX

class Mod_Y:
    modx_obj = ModX()
Copier après la connexion
Copier après la connexion

Ce fichier importe les deux classes (ModX et ModA) de module_1 et module_1_1.

mainpkg/modpkg_x/module_1.py

# module_1.py
class ModX:
   pass

from module_2 import ModY

class Mod_X:
   mody_obj = ModY()
Copier après la connexion
Copier après la connexion

Le module_1 importe une classe ModY du module_2.

mainpkg/modpkg_x/module_1_1.py

# module_2.py
class ModY:
   pass

from module_1 import ModX
Copier après la connexion
Copier après la connexion

Le module_1_1 n'importe rien. Il ne dépend d'aucun module.

mainpkg/modpkg_y/__init__.py

# module_1.py
class ModX:
  pass

class Mod_X:
   from module_2 import ModY
   mody_obj = ModY()
Copier après la connexion
Copier après la connexion

Ce fichier importe la classe ModY du module_2.

mainpkg/modpkg_y/module_2.py

# module_2.py
class ModY:
   pass

class Mod_Y:
   from module_1 import ModX
   modx_obj = ModX()
Copier après la connexion
Copier après la connexion

Le module_2 importe une classe ModA du module_1_1.

Nous avons le code suivant dans le fichier main.py.

root_dir/main.py

# module_1.py
import module_2 as m2

class ModX:
    def __init__(self):
        self.mody_obj = m2.ModY()
Copier après la connexion

Le fichier principal importe une classe ModY du module_2. Ce fichier dépend du module_2.

Si nous visualisons le cycle d'importation ici, cela ressemblerait à ce qui suit en ignorant les fichiers __init__.py dans modpkg_x et modpkg_y.

Different Ways to Fix Circular Imports in Python

On voit que le fichier principal dépend du module_2, le module_1 dépend également du module_2 et le module_2 dépend du module_1_1. Il n'y a pas de cycle d'importation.

Mais vous savez, les modules dépendent de leur fichier __init__.py, donc le fichier __init__.py s'initialise en premier et les modules sont réimportés.

Different Ways to Fix Circular Imports in Python

Voici à quoi ressemble le cycle d'importation maintenant.

Different Ways to Fix Circular Imports in Python

Cela rendait module_1_1 dépendant de module_1, qui est une fausse dépendance.

Si tel est le cas, videz les fichiers __init__.py des sous-packages et l'utilisation d'un fichier __init__.py distinct peut aider en centralisant les importations au niveau du package.

# module_1.py
from module_2 import ModY
class ModX:
    mody_obj = ModY()
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cette structure, nous avons ajouté un autre sous-paquet subpkg dans mainpkg.

mainpkg/subpkg/__init__.py

# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela permettra aux modules internes d'importer à partir d'une source unique, réduisant ainsi le besoin d'importations croisées.

Nous pouvons maintenant mettre à jour l'instruction d'importation dans le fichier main.py.

root_dir/main.py

Traceback (most recent call last):
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
  File "module_2.py", line 1, in <module>
    from module_1 import ModX
  File "module_1.py", line 1, in <module>
    from module_2 import ModY
ImportError: cannot import name 'ModY' from partially initialized module 'module_2' (most likely due to a circular import)
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela résout le problème de dépendance circulaire entre les modules au sein d'un même package.

Conclusion

La dépendance circulaire ou l'importation en Python est une odeur de code qui est une indication d'une restructuration et d'une refactorisation sérieuses du code.

Vous pouvez essayer l'une des méthodes mentionnées ci-dessus pour éviter les dépendances circulaires en Python.


?D'autres articles qui pourraient vous intéresser si celui-ci vous a plu

✅Héritage de modèles dans Flask avec exemple.

✅Différence entre exec() et eval() avec exemples.

✅Comprendre l'utilisation du mot-clé global en Python.

✅Conseils sur le type Python : fonctions, valeurs de retour, variable.

✅Pourquoi la barre oblique et l'astérisque sont utilisés dans la définition des fonctions.

✅Comment le taux d'apprentissage affecte-t-il les modèles ML et DL ?


C'est tout pour le moment.

Continuez à coder✌✌.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
Nordhold: Système de fusion, expliqué
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1673
14
Tutoriel PHP
1278
29
Tutoriel C#
1257
24
Python vs C: courbes d'apprentissage et facilité d'utilisation Python vs C: courbes d'apprentissage et facilité d'utilisation Apr 19, 2025 am 12:20 AM

Python est plus facile à apprendre et à utiliser, tandis que C est plus puissant mais complexe. 1. La syntaxe Python est concise et adaptée aux débutants. Le typage dynamique et la gestion automatique de la mémoire le rendent facile à utiliser, mais peuvent entraîner des erreurs d'exécution. 2.C fournit des fonctionnalités de contrôle de bas niveau et avancées, adaptées aux applications haute performance, mais a un seuil d'apprentissage élevé et nécessite une gestion manuelle de la mémoire et de la sécurité.

Apprendre Python: 2 heures d'étude quotidienne est-elle suffisante? Apprendre Python: 2 heures d'étude quotidienne est-elle suffisante? Apr 18, 2025 am 12:22 AM

Est-ce suffisant pour apprendre Python pendant deux heures par jour? Cela dépend de vos objectifs et de vos méthodes d'apprentissage. 1) Élaborer un plan d'apprentissage clair, 2) Sélectionnez les ressources et méthodes d'apprentissage appropriées, 3) la pratique et l'examen et la consolidation de la pratique pratique et de l'examen et de la consolidation, et vous pouvez progressivement maîtriser les connaissances de base et les fonctions avancées de Python au cours de cette période.

Python vs. C: Explorer les performances et l'efficacité Python vs. C: Explorer les performances et l'efficacité Apr 18, 2025 am 12:20 AM

Python est meilleur que C dans l'efficacité du développement, mais C est plus élevé dans les performances d'exécution. 1. La syntaxe concise de Python et les bibliothèques riches améliorent l'efficacité du développement. Les caractéristiques de type compilation et le contrôle du matériel de CC améliorent les performances d'exécution. Lorsque vous faites un choix, vous devez peser la vitesse de développement et l'efficacité de l'exécution en fonction des besoins du projet.

Python vs C: Comprendre les principales différences Python vs C: Comprendre les principales différences Apr 21, 2025 am 12:18 AM

Python et C ont chacun leurs propres avantages, et le choix doit être basé sur les exigences du projet. 1) Python convient au développement rapide et au traitement des données en raison de sa syntaxe concise et de son typage dynamique. 2) C convient à des performances élevées et à une programmation système en raison de son typage statique et de sa gestion de la mémoire manuelle.

Quelle partie fait partie de la bibliothèque standard Python: listes ou tableaux? Quelle partie fait partie de la bibliothèque standard Python: listes ou tableaux? Apr 27, 2025 am 12:03 AM

PythonlistSaReparmentofthestandardLibrary, tandis que les coloccules de colocède, tandis que les colocculations pour la base de la Parlementaire, des coloments de forage polyvalent, tandis que la fonctionnalité de la fonctionnalité nettement adressée.

Python: automatisation, script et gestion des tâches Python: automatisation, script et gestion des tâches Apr 16, 2025 am 12:14 AM

Python excelle dans l'automatisation, les scripts et la gestion des tâches. 1) Automatisation: La sauvegarde du fichier est réalisée via des bibliothèques standard telles que le système d'exploitation et la fermeture. 2) Écriture de script: utilisez la bibliothèque PSUTIL pour surveiller les ressources système. 3) Gestion des tâches: utilisez la bibliothèque de planification pour planifier les tâches. La facilité d'utilisation de Python et la prise en charge de la bibliothèque riche en font l'outil préféré dans ces domaines.

Python pour l'informatique scientifique: un look détaillé Python pour l'informatique scientifique: un look détaillé Apr 19, 2025 am 12:15 AM

Les applications de Python en informatique scientifique comprennent l'analyse des données, l'apprentissage automatique, la simulation numérique et la visualisation. 1.Numpy fournit des tableaux multidimensionnels et des fonctions mathématiques efficaces. 2. Scipy étend la fonctionnalité Numpy et fournit des outils d'optimisation et d'algèbre linéaire. 3. Pandas est utilisé pour le traitement et l'analyse des données. 4.Matplotlib est utilisé pour générer divers graphiques et résultats visuels.

Python pour le développement Web: applications clés Python pour le développement Web: applications clés Apr 18, 2025 am 12:20 AM

Les applications clés de Python dans le développement Web incluent l'utilisation des cadres Django et Flask, le développement de l'API, l'analyse et la visualisation des données, l'apprentissage automatique et l'IA et l'optimisation des performances. 1. Framework Django et Flask: Django convient au développement rapide d'applications complexes, et Flask convient aux projets petits ou hautement personnalisés. 2. Développement de l'API: Utilisez Flask ou DjangorestFramework pour construire RestulAPI. 3. Analyse et visualisation des données: utilisez Python pour traiter les données et les afficher via l'interface Web. 4. Apprentissage automatique et AI: Python est utilisé pour créer des applications Web intelligentes. 5. Optimisation des performances: optimisée par la programmation, la mise en cache et le code asynchrones

See all articles