Exception Meldung erweitern...

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:

EDIT: Lösung zusammengefasst hier: [wiki]try...except[/wiki]

ich möchte einen Fehler (keinen bestimmten, sondern alle) mit einer Meldung erweitern, weiß gerade nicht wie... Also ungefähr so:

Code: Alles auswählen

try:
    ...mach irgendwas...
except Exception, err:
    raise Exception("Fehler bei BlaBlaBla: %s" % err)
Geht aber so nicht so schön, weil nicht der original Traceback angezeigt wird.

Eine andere Lösung kommt dem schon näher:

Code: Alles auswählen

try:
    ...mach irgendwas...
except Exception, err:
    print "Fehler bei BlaBla..."
    raise
Allerdings ist die zusätzliche Information ja nicht direkt im Traceback eingefügt, sondern wird ja nur mit dem print vorher ausgegeben...

Jemand eine Idee?
Zuletzt geändert von jens am Freitag 19. Juni 2009, 08:32, insgesamt 1-mal geändert.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Was meinst du mit alle Fehler? Also ich hab in einigen meiner
Applikationen schonmal sowas eingebaut:

Code: Alles auswählen

# =========================================
# Exception Handling
def _excepthook(etype, evalue, etb):
    """ Catch all Unhandled Exceptions und report them to the logger """
    trace = traceback.format_exception(etype, evalue, etb)    
    # Do something with trace: "".join(trace))
    sys.__excepthook__(etype, evalue, etb)
   
if not hasattr(sys, "__excepthook__"):
    # python < 2.5
    sys.__excepthook__ = sys.excepthook
sys.excepthook = _excepthook
Das greift aber nur bei unhandled exceptions

Ergänzung: die drei variablen die du brauchst um einen Traceback selber zusammenzubauen bekommst du über sys.exc_info()
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Vielleicht noch ergänzend als Beispiel hinterher:

Code: Alles auswählen

In [5]: try: argh
   ...: except Exception:
   ...:     trace = traceback.format_exception(*sys.exc_info())
   ...:     print "Meine Traceback:\n", "".join(trace)
   ...:
   ...:
Meine Traceback:
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
NameError: name 'argh' is not defined
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also in meinem Falle ist es ein Fehler im unittest. Dort soll schon der traceback "durchschlagen", aber halt mit zusätzlichen Info, ohne die einem der Fehler wenig sagen wird ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Ok ein bisschen gehackt, aber so kannst du die Tracceback message manipulieren

Code: Alles auswählen

In [28]: try: argh
   ....: except:
   ....:     etype, evalue, etb = sys.exc_info()
   ....:     evalue.args = ("Test %s" % (evalue.message,) ,)
   ....:     raise
   ....:
---------------------------------------------------------------------------
<type 'exceptions.NameError'>             Traceback (most recent call last)

C:\<ipython console> in <module>()

<type 'exceptions.NameError'>: Test name 'argh' is not defined
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Geht aber nicht immer. z.Z. bei einem IOError... Probier mal mit file("gibtsnicht", "r")
Außerdem gibt's eine warning, weil ".messages" deprecated ist.

Aber vom Prinzip ist es genau das was ich meinte.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Was spricht gegen Zaps Variante mit format_exc(). Das habe ich z.B. mal verwendet, um Exceptions in eine Messagebox umzuleiten.
MfG
HWK
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Es soll der normal Traceback ausgelöst werden. Ich will ihn nicht wirklich abfangen, sondern nur den Meldungstext erweitern...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Das sich doch auch nur Objekte, warum so kompliziert?

Code: Alles auswählen

In [1]: try:
   ...:     raise IOError("My Own Message.")
   ...: except BaseException, exception:
   ...:     raise exception.__class__("Old message was: '%s'." % exception.message)
   ...: 
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)

/home/str1442/<ipython console> in <module>()

IOError: Old message was: 'My Own Message.'.
Man könnte auch eigene Exceptions definieren, die Zusatzinformationen mittels __init__ aufnehmen oder später setzen lassen und __str__ anpassen, damit das auch gedruckt wird. Man sollte nur Acht geben, das zusätzliche Exception Argumente in __init__ optional sind. Oder man manipuliert direkt <exception>.message und lässt das dann reraisen, müsste auch funktionieren.
Zuletzt geändert von str1442 am Mittwoch 1. April 2009, 14:46, insgesamt 1-mal geändert.
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Ich weiß nicht, ob das jetzt das ist, was du willst, aber logging.exception verlangt einen String, der zusätzlich zum Traceback geloggt wird. Wenn du einen Handler dazupackst, der auf die Konsole loggt, könnte das dann was für dich sein?

Edit: Den obenstehenden Vorschlag mit den eigenen Ausnahmen finde ich allerdings noch eleganter. Verwende ich so an vielen Stellen - weiß nicht, warum ich bei deiner Problembeschreibung nicht darauf gekommen bin :?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Nein so einfach ist das nicht... Also nochmal ein Beispiel:

Code: Alles auswählen

def test2():
    f = file("gibtsnicht", "r")

def test():
    test2()

test()
Ergibt diesen Traceback:

Code: Alles auswählen

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    test()
  File "test.py", line 8, in test
    test2()
  File "test.py", line 5, in test2
    f = file("gibtsnicht", "r")
IOError: [Errno 2] No such file or directory: 'gibtsnicht'
Mit der Lösung:

Code: Alles auswählen

try:
    test()
except Exception, exception:
    raise exception.__class__("Old message was: %r" % repr(exception.args))
kommt aber nur:

Code: Alles auswählen

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    raise exception.__class__("Old message was: %r" % repr(exception.args))
IOError: Old message was: "(2, 'No such file or directory')"
Die Stackliste ist also nicht so wirklich brauchbar...

Ich hätte eigentlich gern sowas:

Code: Alles auswählen

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    test()
  File "test.py", line 8, in test
    test2()
  File "test.py", line 5, in test2
    f = file("gibtsnicht", "r")
IOError: ***Mein Info Text *** [Errno 2] No such file or directory: 'gibtsnicht'

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich würde einfach das gute alte Dekorator-Muster benutzen, dann kann man die verschiedenen Ebenen auch noch auseinander nehmen. Die Ausgabe kannst du darauf komfortabel zusammenbasteln.
Das Leben ist wie ein Tennisball.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Hm, ich hätte jetzt auf sowas getippt:

Code: Alles auswählen

In [1]: try:
   ...:     raise IOError("Text")
   ...: except IOError, exception:
   ...:     exception.message = "My New Message"
   ...:     raise exception
   ...: 
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)

/media/Daten/bla/<ipython console> in <module>()

IOError: Text
Aber das funktioniert komischerweise nicht... Da müsste also der Traceback neu generiert werden. Kann das mal wer in Python 3 testen? Hätte man ja mit zb. einer Property für alle wichtigen Attribute einer Exception regeln können.

Ansonsten ist vielleicht noch das hier zu Exceptions und 3.0 interessant:

http://www.python.org/dev/peps/pep-3134/

Da gehts aber darum, verschiedene Exceptions zu "verbinden".
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Ok ich geb auch noch einen zum Besten:

Code: Alles auswählen

In [1]: import sys

In [2]:

In [2]: try: open("doesnotexist")
   ...: except:
   ...:         etype, evalue, etb = sys.exc_info()
   ...:     evalue = etype("Additional Info\n%s" % evalue)
   ...:     raise etype, evalue, etb
   ...:
---------------------------------------------------------------------------
<type 'exceptions.IOError'>               Traceback (most recent call last)

c:\<ipython console> in <module>()

<type 'exceptions.IOError'>: Additional Info
[Errno 2] No such file or directory: 'doesnotexist'

Mich wundert sehr das .message deprecated ist. Muss ich mal nachschauen was die Alternative ist
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

@Zap: Ja, das macht genau das was ich suche ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Zur Info:
Auf Ian Bickings Blog gibts eine schöne Übersicht und Diskussion zu verschiedensten Problemkonstellationen rum um Exceptions und mögliche Lösungen:
http://blog.ianbicking.org/2007/09/12/r ... xceptions/
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Nochmal zusammen gefasst hier: [wiki]try...except[/wiki]

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mit python 3.0 gibt es auch ein paar neue Felder auf Exceptions wie in etwa "__cause__". Man kann dann mit "raise MyException() from old_exception" diese Funktionalität nutzen. Näheres kann ich dazu aber nicht sagen, da ich mich damit noch nicht beschäftigt habe.
Antworten