import loops...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Immer öfters schlage ich mich mit import loops herum.

Bei PyLucid ist die models.py einfach zu groß geworden. Also hab ich es in ein Package verwandelt.
Es gibt allerdings diverse Abhängigkeiten zwischen den Modellen. Zwar kann man z.B. beim models.ForeignKey() einen String übergeben, statt direkt dem Objekt. Aber an manchen Stellen brauche ich anderen Model Klassen.
Als Lösung kann man den import von Modulebene in die Klasse verschieben, aber das ist unschön ist.

Welche Strategien nutzt ihr dafür?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
lunar

Die einzig wirklich sinnvolle Strategie ist eigentlich, solche Abhängigkeiten gar nicht erst entstehen zu lassen. Wenn Du viele zirkuläre Abhängigkeiten hast, ist das Design wohl verbesserungsbedürftig. Eine große Anzahl zirkulärer Abhängigkeiten ist eigentlich ein Zeichen dafür, dass die Klassen, die Du auf verschiedene Module verteilt hast, wohl eher in ein einziges Modul gehören, oder zumindest in ein Paket, dass dann auf Paketebene die einzelnen Module verbindet.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Naja, Modelle die mit FK oder M2M verbunden sind haben halt was miteinander zu tun...

Das Problem ist auch: Ich finde es schwer das ganze zu debuggen. Denn man bekommt nur den Fehler "ImportError: cannot import name FooBar". Was interessant wäre, warum python das Modul nicht importieren kann :evil:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Du solltest dir klarmachen, wie der Importmechanismus von Python funktioniert. Python kann die Module sehr wohl importieren, faktisch sind sie ja sogar schon importiert (und der Code darin wird gerade ausgeführt), nur die Namen im Modul existieren eben noch nicht.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hast recht. Aber dennoch hilft die Fehlermeldung erstmal nicht weiter.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Was soll Python auch groß anders sagen? "Hilfe, du hast einen zirkulären Import!"? Aus Sicht von Python kann eben der Name nicht gefunden werden und nichts anderes. Und woran es liegt, wird, wenn man Python kennt, auch recht schnell klar, denn das schöne an Python ist ja, dass man für Ausnahmen Tracebacks für umsonst bekommt und nicht erst einen Debugger oder sonst etwas anwerfen muss.

Nehmen wir also an, ich habe ein Modul `main`, das `a` importiert. `a` hat irgendwas an den Namen `A` gebunden. Zuvor importiert `a` jedoch das Modul `b` und `b` importiert wiederum aus `A` aus `a`. Also:

Code: Alles auswählen

# main
import a


#a
import b

A = 42


# b
from a import A
Wenn man das jetzt ausführt, wird eine Ausnahme geworfen und man erhält einen Traceback.

Code: Alles auswählen

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import a
  File "a.py", line 1, in <module>
    import b
  File "b.py", line 1, in <module>
    from a import A
ImportError: cannot import name A
Also schaut man sich an, was passiert. Wenn man in `main` anfängt, sieht man, dass `a` importiert wird. Also macht man sich klar, was das bedeutet. Das Modul wird gesucht, geparst usw., dann wird ein Modulobjekt in `sys.modules` gesteckt und dann wird einfach der Code im Modul ausgeführt, der dann von oben nach unten abläuft. Danach sieht man, dass eben der Code in `a` wiederum `b` importiert. Der Ablauf ist analog zu `a`. Und dann sieht man, dass in `b` eben wieder `a` importiert wird. Was passiert jetzt aber hier? Module werden in Python gecachet, weshalb `a` nicht noch einmal neu geladen wird, sondern es wird das Modulobjekt aus `sys.modules` verwendet. Da der Code im Modul jedoch von oben nach unten ausgeführt wird, `A` in `a` also erst nach der Importanweisung erstellt wird, kann `A` eben nicht importiert werden. Würde man jetzt beispielsweise das Modul `a` so ändern:

Code: Alles auswählen

# a
A = 42

import b
würde keine Ausnahme geworfen werden.

Von daher ist ein zirkulärer Import IMHO also nicht unbedingt schwer zu debuggen (immerhin ist er völlig offensichtlich im Traceback zu erkennen), sondern kann eher auf Grund fehlender Kenntnisse über den Importmechanismus nicht erklärt werden.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Antworten