2015-09-14 2 views
0

Comment casser cette importation circulaire particulière. J'ai ajouté un exemple trivial ajouté en haut pour mettre en évidence le problème.Briser les importations circulaires de Python

module_tit.py

import tat 
class Tit 
    def tit(x): 
     return tat.inst.tat(x) 

inst = Tit() 

if __name__=='__main__: 
    print "tit 12 %s" % inst.tit(12) 

module_tat.py

import tit 
class Tat: 
    def tat(x): 
     if x>0: return tit.inst.tit(x-1) 
     else: return 'bottom' 

inst = Tat() 

if __name__=='__main__: 
    print "tat 5 %s" % inst.tat(5) 
  • La conception de mon code exige fermement que tit et tat soient dans leurs propres modules.
  • Il est important que le tit ou tat puisse être le premier module chargé.
  • Est-ce possible en python de quelque façon que ce soit ???

question === === originale ci-dessous

J'ai un base_module avec plusieurs dizaines de constantes, etc., il est importé par beaucoup, et il importe rien. J'y ai une classe clé dans le module de base, et il dépend d'un joli module d'imprimante pour faire l'impression de chose:

to_str = None 
class Thing_Version1(object): 
    def __repr__(): 
     to_str(self) 

Dans le joli module imprimante je:

def to_str(x): 
    ... 
import base_module 
base_module.to_str = to_str 

Lorsque le joli module d'imprimante qu'il définit "base_module.to_str" pour que tout fonctionne correctement. cela fonctionne 99% du temps, mais dans le débogueur, il n'est pas assez intelligent pour charger la jolie imprimante (même si dans l'interpréteur normal, mon processus de chargement force la charge éventuelle du module pprint. importer dynamiquement:

class Thing_Version1(object): 
    def __repr__(): 
     import pprint 
     pprint.to_str(self) 

Mais cela échoue aussi parfois ne peut pas trouver la fonction « to_str » dans le module pprint (je suppose en raison de référence circulaire)

Mon but ultime est de forcer le chargement de pprint. à chaque fois que load_module est chargé, et que permet à pprint de dépendre des dizaines de constantes dans le module_base

Est-ce impossible?

+0

Je ne crois pas que cela ait quelque chose à voir avec les références circulaires.Vous devriez importer pprint dans le module de base car c'est là que se trouve le contrat. Si vous l'importez localement, alors la portée des objets importés est seulement dans cette fonction locale, donc toute autre personne souhaitant utiliser 'pprint.to_str()' devra également importer 'pprint'. Vous devez vous rappeler que python est résolu dynamiquement, donc 'x = 0; def p(): imprimer (x); x = 1; p() 'affiche 1 et non 0. – AChampion

+2

Pourriez-vous donner un [mcve] qui montre mieux ce que vous essayez d'accomplir? Où ces constantes sont-elles définies et que pprint requiert, et pourquoi ne les empaquetez-vous pas dans une fonction/un module utilitaire pour le reste de votre projet? – jonrsharpe

+0

@achampion pprint doit importer base_module car il a des dizaines de constantes nécessaires etc. maintenant vous me dites d'effectuer l'importation de pprint dynamiquement afin de briser le cycle. Cela sonne bien, et si vous regardez mon deuxième bloc de code ci-dessus, vous verrez que j'ai une importation dynamique de pprint pendant l'impression de l'objet. Cela fonctionne 99% du temps. parfois, le module pprint n'aura pas la fonction to_str. Je pense que cela se produit quand un module est chargé de manière circulaire. par exemple. quand lors de l'exécution de son premier chargement, il a importé un module qui l'a réimporté récursivement. Je ne vois pas comment éviter! –

Répondre

1

Malheureusement, je ne peux pas reproduire votre problème. Python a une résolution dynamique des références si circulaires sont rarement un problème:

fred.py

import wilma 
count = 4 
def main(): 
    wilma.pr('Hello') 

wilma.py

import fred 
def pr(str): 
    print(str*fred.count) 

Python REPL

>>> import fred 
>>> fred.main() 
HelloHelloHelloHello 

Essayez-vous trop pour éviter un problème qui se produit rarement en Python? Pouvez-vous fournir un exemple minimal du problème que vous rencontrez?

+0

Dans chacun de mes modules, j'ai typiquement une variable 'inst' qui contiendra un singleton pour les classes (comme une imprimante) où vous en utilisez souvent un seul. Le code de ces variables 'inst' s'exécute au moment de LOAD. Il peut donc se bloquer s'il tente de tirer parti des dépendances d'autres classes qui sont elles-mêmes en train de se charger dynamiquement. Mon but est d'avoir des objets init dans les classes où leur code source est, et d'être créé automatiquement. mais peut-être que cela ne peut pas arriver. –

+0

J'accepte votre réponse, c'est correct, mais je n'ai jamais réussi à exprimer mon vrai numéro. Mon code a toujours été exécuté dans l'interpréteur, mais sa méthode __repr __() ne s'est pas exécutée lors de l'impression des valeurs dans la fenêtre du débogueur. mais en supprimant de plus en plus le code d'initialisation, j'ai fini par le faire fonctionner ... mais je ne sais pas vraiment ce qui était différent entre l'environnement de débogage interne. et l'environnement principal. Merci –