recherche
Maisondéveloppement back-endTutoriel PythonDifférentes façons de corriger les importations circulaires en Python

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()
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()

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)
</module></module></module>

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

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()
# module_2.py
from main import ModX

class Mod_Y:
    modx_obj = ModX()

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()
# module_2.py
class ModY:
   pass

from module_1 import ModX

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()
# module_2.py
class ModY:
   pass

class Mod_Y:
   from module_1 import ModX
   modx_obj = ModX()

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()
# module_2.py
from module_1 import ModX
class ModY:
    modx_obj = ModX()

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)
</module></module></module>
# main.py ----> common file
class ModX:
    pass

class ModY:
    pass

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()

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()

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()

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

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()

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()

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()

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()

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()

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)
</module></module></module>

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
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
Quelles sont les raisons courantes pour lesquelles un script Python pourrait ne pas s'exécuter sur Unix?Quelles sont les raisons courantes pour lesquelles un script Python pourrait ne pas s'exécuter sur Unix?Apr 28, 2025 am 12:18 AM

Les raisons pour lesquelles les scripts Python ne peuvent pas fonctionner sur les systèmes UNIX incluent: 1) des autorisations insuffisantes, en utilisant Chmod xyour_script.py pour accorder des autorisations d'exécution; 2) Ligne Shebang incorrecte ou manquante, vous devez utiliser #! / Usr / bin / enwpython; 3) Paramètres de variables d'environnement incorrectes, vous pouvez imprimer OS.environ Debogging; 4) En utilisant la mauvaise version Python, vous pouvez spécifier la version sur la ligne Shebang ou la ligne de commande; 5) Problèmes de dépendance, en utilisant un environnement virtuel pour isoler les dépendances; 6) Erreurs de syntaxe, utilisez python-mpy_compileyour_script.py pour détecter.

Donnez un exemple de scénario où l'utilisation d'un tableau Python serait plus appropriée que l'utilisation d'une liste.Donnez un exemple de scénario où l'utilisation d'un tableau Python serait plus appropriée que l'utilisation d'une liste.Apr 28, 2025 am 12:15 AM

L'utilisation de tableaux Python est plus adapté au traitement de grandes quantités de données numériques que les listes. 1) Les tableaux économisent plus de mémoire, 2) les tableaux sont plus rapides pour fonctionner par des valeurs numériques, 3) la cohérence de type de force des tableaux, 4) Les tableaux sont compatibles avec les tableaux C, mais ne sont pas aussi flexibles et pratiques que les listes.

Quelles sont les implications de performances de l'utilisation des listes par rapport aux tableaux dans Python?Quelles sont les implications de performances de l'utilisation des listes par rapport aux tableaux dans Python?Apr 28, 2025 am 12:10 AM

Listes sont une meilleure ancêtres et des datatatates de mix

Comment Numpy gère-t-il la gestion de la mémoire pour les grandes tableaux?Comment Numpy gère-t-il la gestion de la mémoire pour les grandes tableaux?Apr 28, 2025 am 12:07 AM

NumpyManagesMemoryForLargeArraySEfficientlyUsingViews, Copies andMemory-MapyPiles.1) Vues Allowcing withoutcopy

Qui nécessite l'importation d'un module: listes ou tableaux?Qui nécessite l'importation d'un module: listes ou tableaux?Apr 28, 2025 am 12:06 AM

ListSinpythondonoTequireImporttingAmodule, tandis que les listes de la part de la variation de la daymoduleeeedanimport.1)

Quels types de données peuvent être stockés dans un tableau Python?Quels types de données peuvent être stockés dans un tableau Python?Apr 27, 2025 am 12:11 AM

PythonlistScanstoreanyDatatype, ArrayModulearRaySstoreOneType, et NumpyArraysArnumericalComptations.1) ListesaSaSatilebutlessmemory-Efficient.2) NumpyArraySareMory-EfficientForHomoGeneousData.3)

Que se passe-t-il si vous essayez de stocker une valeur du mauvais type de données dans un tableau Python?Que se passe-t-il si vous essayez de stocker une valeur du mauvais type de données dans un tableau Python?Apr 27, 2025 am 12:10 AM

Lorsque vous vous assumez de la valeur de la valeur de la datyypie de la datyylethonarray.

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.

See all articles

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 !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

DVWA

DVWA

Damn Vulnerable Web App (DVWA) est une application Web PHP/MySQL très vulnérable. Ses principaux objectifs sont d'aider les professionnels de la sécurité à tester leurs compétences et leurs outils dans un environnement juridique, d'aider les développeurs Web à mieux comprendre le processus de sécurisation des applications Web et d'aider les enseignants/étudiants à enseigner/apprendre dans un environnement de classe. Application Web sécurité. L'objectif de DVWA est de mettre en pratique certaines des vulnérabilités Web les plus courantes via une interface simple et directe, avec différents degrés de difficulté. Veuillez noter que ce logiciel

Dreamweaver Mac

Dreamweaver Mac

Outils de développement Web visuel

Listes Sec

Listes Sec

SecLists est le compagnon ultime du testeur de sécurité. Il s'agit d'une collection de différents types de listes fréquemment utilisées lors des évaluations de sécurité, le tout en un seul endroit. SecLists contribue à rendre les tests de sécurité plus efficaces et productifs en fournissant facilement toutes les listes dont un testeur de sécurité pourrait avoir besoin. Les types de listes incluent les noms d'utilisateur, les mots de passe, les URL, les charges utiles floues, les modèles de données sensibles, les shells Web, etc. Le testeur peut simplement extraire ce référentiel sur une nouvelle machine de test et il aura accès à tous les types de listes dont il a besoin.

SublimeText3 version Mac

SublimeText3 version Mac

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