Tool zur Ermittlung von kreisförmigen Importe in Python/Django?
Habe ich eine Django-app und irgendwo in es ist ein rekursiver import, das Probleme verursacht. Aufgrund der Größe der app, ich habe da ein problem das aufzeigen der Ursache des kreisrunden importieren.
Ich weiß, dass die Antwort ist "einfach nicht schreiben zirkuläre Importe" aber das problem ist ich habe eine harte Zeit, herauszufinden, wo der kreisförmigen import aus, so dass im Idealfall ein tool, verfolgt das importieren zurück auf seine Herkunft wäre ideal.
Solch ein tool gibt? Abgesehen, dass ich das Gefühl, ich mache alles was ich kann, um zu vermeiden, circular import Probleme-Umzug-Importe an den unteren Rand der Seite, wenn möglich, verschieben Sie Sie innerhalb von Funktionen, anstatt Sie an der Spitze, etc. aber immer noch Probleme. Ich Frage mich, ob es irgendwelche Tipps oder tricks für die Vermeidung von Ihnen insgesamt.
Zu erarbeiten, ein bisschen...
In Django speziell wenn es auf einer kreisförmigen importieren, manchmal wirft es ein Fehler sein, aber manchmal geht es durch leise aber Ergebnisse in einer situation, wo bestimmte Modelle oder Felder einfach nicht, es. Frustrierend, geschieht dies oft in einem Kontext (sagen wir, das WSGI-server) und in der anderen nicht (die shell). So testen in der shell so etwas wie dies funktionieren wird:
Foo.objects.filter(bar__name='Test')
aber in der web-wirft den Fehler:
FieldError: Cannot resolve keyword "bar__name' ins Feld. Auswahlmöglichkeiten sind: ...
Mit mehreren Bereichen Auffällig fehlt.
Also kann es nicht ein einfaches problem mit dem code, da es hat arbeiten in der shell, aber nicht über die website.
Einige Tools, die herausfand, war genau das, was Los wäre große. ImportError
ist vielleicht die am wenigsten hilfreich Ausnahmemeldung je.
- python -vv wird Hilfe bei der Suche rekursiv Einfuhren. Beispiel: pastebin.com/3HpYgeC2
- Gibt es eine Möglichkeit, zu organisieren, diese Ausgabe in einer Weise, so kann ich sehen, was aufgerufen wurde? Scheint so, das würde nur Arbeit für schwer-Rundschreiben-import-Probleme nicht die weichen, wie ich habe...
- (Ich bin nicht sicher, ob dies wird Euch helfen, denn ich bin mir nicht sicher, wie Sie es in Ihrem WSGI-Umgebung). Sowieso, kann es helfen, mit "weichen"/"runtime" - Probleme beim import. Wie die Linie 627 der paste, wo ich einen Anruf manuell "importieren " django": es zeigt alle Dateien, die es versucht. Ich habe gerade getestet "import django.db" und zeigt alle Dateien, die es versucht, für alle Module, die von django.db. Ich weiß nicht, aber würde gerne wissen, eine bestehende Art und Weise das Ergebnis verbessern, weil es ist ein Schmerz, den ich vollkommen Zustimmen!!!
- Die silent scheitern ist, weil Sie mehrere Module mit dem gleichen Namen. Dann, python import Bestellung (basierend auf pythonpath) ist die Referenz. Oh, wenn/wenn Sie den Namen ändern, stellen Sie sicher, entfernen Sie die
.pyc
auch 🙂 (ist es mir mehrmals passiert)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Ursache des import-Fehler ist schnell gefunden, in der backtrace des ImportError-Ausnahme.
Beim Blick in den backtrace, wirst du sehen, dass das Modul importiert wurde, vor. Einer der es importiert importiert etwas anderes ausgeführt, Haupt-code und importiert nun das erste Modul. Da das erste Modul wurde nicht vollständig initialisiert (es war immer noch stecken Sie es in die import-code), erhalten Sie jetzt die Fehler der Symbole nicht gefunden. Was Sinn macht, weil die Haupt-code des Moduls nicht erreichen, dass die Stelle doch.
Häufigsten Ursachen in Django sind:
Importieren subpackage aus einem ganz anderen Modul,
z.B.
from mymodule.admin.utils import ...
Dieser lädt
admin/__init__.py
ersten, die wahrscheinlich importiert, während die Last von anderen Paketen (z.B. Modelle, admin-views). Der admin-view wird initialisiert mitadmin.site.register(..)
so an den Konstruktor könnte zu importieren, mehr Zeug. Irgendwann treffen könnte, Ihre Modul-Ausgabe der ersten Anweisung.Hatte ich eine solche Aussage in meinem middleware, können Sie erraten, wo das geendet hat mich mit. 😉
Mischen von form-Feldern, - widgets und-Modelle.
Da das Modell kann ein "formfield" starten Sie den Import-Formulare. Es hat ein widget. Das widget hat einige Konstanten aus .. äh... das Modell. Und jetzt haben Sie eine Schleife. Besser importieren Sie das Formular-Feld Klasse in den
def formfield()
Körper statt der globalen Modul-Umfang.Einen
managers.py
bezieht sich auf Konstantenmodels.py
Nachdem alle, das Modell muss der manager zunächst. Der manager kann nicht gestartet werden, importieren
models.py
denn es war noch initialisiert werden. Siehe unten, denn dies ist die einfachste situation.Mit
ugettext()
stattugettext_lazy
.Wenn Sie
ugettext()
die übersetzung system muss initialisiert werden. Es läuft ein scan über alle Pakete inINSTALLED_APPS
auf der Suche nach einemlocale.XY.formats
Paket. Wenn Ihre app wurde nur initialisiert sich, es wird nun wieder importiert von der globalen Modul-scan.Ähnliche Dinge passieren, mit einem scan für plugins, search_indexes von Heuhaufen, und anderen ähnlichen Mechanismen.
Setzen viel zu viel in
__init__.py
.Dies ist eine Kombination der Punkte 1 und 4, es betont die import-system, da ein import von subpackage wird zuerst die Initialisierung aller übergeordneten Pakete. In der Tat eine Menge von code, der ausgeführt wird, um einen einfachen import und erhöht die änderungen importieren zu müssen etwas vom falschen Ort.
Die Lösung ist nicht schwer entweder. Sobald Sie eine Idee haben von, was die Ursache für die Schleife, Sie zu entfernen, dass import-Anweisung aus der weltweiten Importe (am Anfang der Datei) und legen Sie Sie in eine Funktion, die verwendet das symbol. Zum Beispiel:
In diesem Fall können Sie sehen
models.py
wirklich braucht, um zu importierenmanagers.py
; ohne Sie kann es nicht tun, die statische Initialisierung vonPageManager
. Anders herum ist nicht so wichtig. DiePage
- Modell könnten leicht importiert werden innerhalb einer Funktion statt Global.Das gleiche gilt für jede andere situation der import-Fehler. Die Schleife kann ein paar mehr Pakete jedoch.
ugettext
habe ich auch. Big props!Page
Modell im manager? Manager selbst hat seine Attributmodel
.Einer der häufigsten Ursachen für kreisrunden Importe in Django ist über Fremdschlüssel in Module, die aufeinander verweisen. Django bietet eine Möglichkeit um dies zu umgehen, indem Sie explizit angeben eines Modells als string mit der vollständigen Anwendung label:
Finden Sie unter: https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey
from myapp import MyAppModel
ist, entfernen Sie diese Zeile und Sie stattdessen tun, wie oben, setzen'myapp.MyAppModel'
im Fremdschlüssel.Was ich normalerweise Tue, wenn ich auf einen import-Fehler ist, meinen Weg zu arbeiten rückwärts. Ich würde einige "nicht importieren xyz von myproject.Blick" - Fehler, obwohl xyz existiert nur in Ordnung. Dann habe ich zwei Dinge tun:
Ich grep meinem eigenen code für jedes import von myproject.Aussicht und eine (mentale) Liste der Module, die Sie importieren.
Ich prüfen, ob ich den import einer von denen passende Module in views.py wiederum. Oft gibt Ihnen der Schuldige ist.
Einen gemeinsamen Punkt, wo es schief gehen kann, ist Ihre models.py. Oft zentrale, was du tust. Aber stellen Sie sicher, Sie versuchen, halten Sie Ihre Importe zeigen models.py statt von ihm Weg. So importieren Sie Modelle aus views.py, aber nicht die andere Weise herum.
Und in urls.py ich normalerweise zu importieren, die meine Ansichten (da bekomme ich einen schönen sofortigen import-Fehlermeldung, wenn ich einen Fehler machen, die Art und Weise). Aber um zu verhindern, dass zirkuläre importieren Fehler auftreten, können Sie auch beziehen sich auf Ihre Ansichten mit einer gestrichelten Pfad-string. Aber das hängt davon ab, was Sie tun in Ihrem urls.py.
Einen Kommentar bezüglich Platzierung der Importe: halten Sie Sie an den Anfang der Datei. Wenn Sie ausbreiten, Sie werden nie ein klares Bild von dem Modul importiert, was. Nur indem wir Sie alle an der Spitze (schön sortiert) könnte bereits helfen Ihnen, Probleme zu ermitteln. Import nur innerhalb der Funktion, wenn notwendig, für die Lösung einer bestimmten, kreisförmigen importieren.
Machen und Ihre Importe mit absoluten statt relativen. Ich meine "from myproject.Ansichten import xyz" anstelle von "von Ansichten import xyz". So dass es absolut kombiniert mit der Sortierung der Liste der Importe macht Ihre Importe mehr klar und sauber.
Nur die Umwandlung der Kommentar oben in einer Antwort...
Wenn Sie haben kreisförmige import
python -vv
funktioniert der trick. Andere Möglichkeit wäre, um eine überlastung der Modul-loader (es gibt ein link irgendwo, aber ich finde, es ist nicht nur jetzt). Update: Sie können sich wahrscheinlich tun Sie es mit der ModuleFinderDie automatische Fehler passiert, weil Sie mehrere Module mit dem gleichen Namen. Dann, python import Bestellung (basierend auf pythonpath) ist die Referenz. Oh, wenn/wenn Sie den Namen ändern, stellen Sie sicher, entfernen Sie die
.pyc
auch 🙂 (ist es mir mehrmals passiert)