Python Komplexere Exception catchen

NJay

Rear Admiral
Registriert
Aug. 2013
Beiträge
5.514
Hallo,

ich arbeite gerade am Django Tutorial. Nun kann es vorkommen, dass der Nutzer eine Seite mit einem element aus der DB angezeigt bekommen möchte, die es nicht gibt. Mein Programm versucht also den Datenbankeintrag zu laden und wenn es ihn nicht gibt, wirf er folgende Exception:

Code:
pollTest.models.Picture.DoesNotExist: Picture matching query does not exist.

Diese Exception möchte ich nun catchen um den Fehlerfall abzufangen. Der Code:

Code:
try:
    p = Picture.objects.get(pk=picture_id)
except pollTest.models.Picture.DoesNotExist:
    p = "There is no picture with id = " + str(picture_id)

Funktioniert jedoch nicht. Er findet die Exception nicht, was einen Name Error verursacht:

Code:
NameError: name 'pollTest' is not defined

Wie kann das sein? Es gibt den Ordner pollTest und es ist ja exakt der Pfad, den der Interpreter als Exception wird, 1 zu 1 kopiert.

Was mache ich falsch? Ich konnte im Internet nichts zu diesem Fehler finden.
Ich hatte das Problem in einem anderen Projekt (ohne Django, mit Thrift) genauso, da konte ich es nicht lösen und habe es ignoriert, was leider keine gute Idee war :D

Vielen Dank für eure Hilfe.

Edit: Habe das Problem durch ausprobieren gelöst. Kann mir einer eventuell erklären warum das das Problem ist? Liegt es daran, dass ich Picture oben im code importiere?

Code:
from .models import Picture

Der Catch block muss lauten:

Code:
try:
    p = Picture.objects.get(pk=picture_id)
except Picture.DoesNotExist:
    p = "There is no picture with id = " + str(picture_id)
 
Zuletzt bearbeitet:
Except muss auf der gleichen Höhe sein wie try, oder?
Also except ist kein Block innerhalb von try, sondern sollte ein neuer Block direkt im Anschluss des try Blocks sein.
 
Nach except muss eine tatsächliche Exception stehen. Also soetwas wie NameError, TypeError oder ValueError. Kannst du mal die komplette Ausgabe des Picture.objects.get() Befehls posten? Ansonsten könnte es natürlich sein, dass das gar keine wirkliche Exception gibt, sondern einfach einen besonderen Rückgabewert, den du mit if...else abfangen könntest.
 
KingLz schrieb:
Except muss auf der gleichen Höhe sein wie try, oder?
Also except ist kein Block innerhalb von try, sondern sollte ein neuer Block direkt im Anschluss des try Blocks sein.

Da ist beim kopieren was schef gelaufen. Im code ist es richtig eingerückt.
Ergänzung ()

stupidus schrieb:
Nach except muss eine tatsächliche Exception stehen. Also soetwas wie NameError, TypeError oder ValueError. Kannst du mal die komplette Ausgabe des Picture.objects.get() Befehls posten? Ansonsten könnte es natürlich sein, dass das gar keine wirkliche Exception gibt, sondern einfach einen besonderen Rückgabewert, den du mit if...else abfangen könntest.

Code:
    p = Picture.objects.get(pk=picture_id)
  File "/usr/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/lib/python3.7/site-packages/django/db/models/query.py", line 408, in get
    self.model._meta.object_name
pollTest.models.Picture.DoesNotExist: Picture matching query does not exist.

Es ist wirklich eine Exception, mit gekürztem Pfad funktioniert es jetzt ja auch.
 
Es hätte vielleicht auch mit "import pollTest" funktioniert. Eventuell fehlt im pollTest-Ordner noch die Datei init.py (Mit zwei Unterstrichen jeweils vor und nach init, die Forensoftware lässt mich das nicht schreiben)
 
Polltest ist wohl das Python module, Models ist die Datei aus der importiert wird und Picture ist die Klasse.
(das ist halb geraten ich kenn ja nicht alles)

Mit from .models import Picture macht du die Klasse Picture in deinem Code verfügbar.
Diese Klasse Pictures hat vermutlich von einer Djangobasisklasse die DoesNotExist Exception vererbt bekommen.

Die Basisexception ist übrigens hier definiert:

https://docs.djangoproject.com/en/2.2/ref/models/instances/#django.db.models.Model.DoesNotExist

Du könntest also evtl from django.core.exceptions import DoesNotExist probieren und wenn es die Exception da gibt einfach auf DoesNotExist testen.

Ich finde allerdings nur ObjectDoesNotExist Exception. Welche Django Version benutzt du denn?
 
  • Gefällt mir
Reaktionen: NJay
KingLz schrieb:
Polltest ist wohl das Python module, Models ist die Datei aus der importiert wird und Picture ist die Klasse.
(das ist halb geraten ich kenn ja nicht alles)

Mit from .models import Picture macht du die Klasse Picture in deinem Code verfügbar.
Diese Klasse Pictures hat vermutlich von einer Djangobasisklasse die DoesNotExist Exception vererbt bekommen.

Die Basisexception ist übrigens hier definiert:

https://docs.djangoproject.com/en/2.2/ref/models/instances/#django.db.models.Model.DoesNotExist

Du könntest also evtl from django.core.exceptions import DoesNotExist probieren und wenn es die Exception da gibt einfach auf DoesNotExist testen.

Das geratene stimmt so alles. Die basisklasse habe ich in der Doku auch gefunden gehabt, das hat mir aber nicht weitergeholfen.

Die init ist überall vorhanden.

So wie ich es jetzt verstanden habe muss man immer genau die exception nach den imports catchen, also so, wie man auchauf die Klasse zugreifen kann.

Vielen Dank.
 
Naja du musst eigentlich wissen wo die Exception definiert ist und es von dort importieren.
Du könntest vermutlich from django.core.exceptions import * machen und dann einfach nur den Namen benutzen.

Exceptions sind anscheinend auch nur besonders definierte Klassen, d.h. du musst nur die Deklaration finden.

https://www.programiz.com/python-programming/user-defined-exception

DoesNotExist muss also irgendwo die Basisklasse sein.
 
  • Gefällt mir
Reaktionen: NJay
KingLz schrieb:
Exceptions sind anscheinend auch nur besonders definierte Klassen, d.h. du musst nur die Deklaration finden.

https://www.programiz.com/python-programming/user-defined-exception

DoesNotExist muss also irgendwo die Basisklasse sein.

Ja das habe ich jetzt auch verstanden. Ich bin halt davon ausgegangen, dass wenn der Interpreter Exception X.Y.Z meldet, ich genau X.Y.Z catchen kann. Das ist aber nicht der Fall. Wenn ich z.B. X schon importiert habe (bei mir oben so), su muss ich Y.Z catchen.

Vielen Dank für deine Hilfe!
 
Zurück
Oben