84 votes

Dépendance d'importation circulaire en Python

Supposons que j'aie la structure de répertoire suivante :

a\
    __init__.py
    b\
        __init__.py
        c\
            __init__.py
            c_file.py
        d\
            __init__.py
            d_file.py

Dans le cadre de la a du paquet __init__.py , le c est importé. Mais c_file.py importations a.b.d .

Le programme échoue en disant b n'existe pas lorsque c_file.py tente d'importer a.b.d . (Et il n'existe pas vraiment, car nous étions en train de l'importer).

Comment remédier à ce problème ?

1 votes

Peut-être pourriez-vous essayer les importations relatives ? stackoverflow.com/questions/72852/

1 votes

0 votes

Également à titre de référence, il semble que les importations circulaires soient autorisées sous Python 3.5 (et probablement au-delà) mais pas sous 3.4 (et probablement en dessous).

0voto

RaamEE Points 397

Je propose le modèle suivant. Son utilisation permettra à l'autocomplétion et à l'indication de type de fonctionner correctement.

cyclic_import_a.py

import playground.cyclic_import_b

class A(object):
    def __init__(self):
        pass

    def print_a(self):
        print('a')

if __name__ == '__main__':
    a = A()
    a.print_a()

    b = playground.cyclic_import_b.B(a)
    b.print_b()

cyclic_import_b.py

import playground.cyclic_import_a

class B(object):
    def __init__(self, a):
        self.a: playground.cyclic_import_a.A = a

    def print_b(self):
        print('b1-----------------')
        self.a.print_a()
        print('b2-----------------')

Vous ne pouvez pas importer les classes A et B en utilisant cette syntaxe

from playgroud.cyclic_import_a import A
from playground.cyclic_import_b import B

Vous ne pouvez pas déclarer le type du paramètre a dans la méthode de la classe B __ init __, mais vous pouvez le "mouler" de cette façon :

def __init__(self, a):
    self.a: playground.cyclic_import_a.A = a

-4voto

user474491 Points 222

Une autre solution consiste à utiliser un proxy pour le fichier d_file.

Par exemple, supposons que vous souhaitiez partager la classe blah avec le fichier c. Le fichier d contient donc :

class blah:
    def __init__(self):
        print("blah")

Voici ce qu'il faut entrer dans c_file.py :

# do not import the d_file ! 
# instead, use a place holder for the proxy of d_file
# it will be set by a's __init__.py after imports are done
d_file = None 

def c_blah(): # a function that calls d_file's blah
    d_file.blah()

Et dans un init .py :

from b.c import c_file
from b.d import d_file

class Proxy(object): # module proxy
    pass
d_file_proxy = Proxy()
# now you need to explicitly list the class(es) exposed by d_file
d_file_proxy.blah = d_file.blah 
# finally, share the proxy with c_file
c_file.d_file = d_file_proxy

# c_file is now able to call d_file.blah
c_file.c_blah()

11 votes

La modification des attributs globaux d'un module dans un fichier différent comme celui-là conduira rapidement à un cauchemar.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X