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.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Exception Meldung erweitern...

Beitragvon jens » Mittwoch 1. April 2009, 10:50

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.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Mittwoch 1. April 2009, 11:38

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

Beitragvon Zap » Mittwoch 1. April 2009, 11:46

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 1. April 2009, 11:54

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 ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Mittwoch 1. April 2009, 12:10

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 1. April 2009, 12:33

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.

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

Beitragvon HWK » Mittwoch 1. April 2009, 14:20

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 1. April 2009, 14:21

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

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

Beitragvon str1442 » Mittwoch 1. April 2009, 14:44

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

Beitragvon Pekh » Mittwoch 1. April 2009, 14:46

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 1. April 2009, 14:52

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=]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')"[/code]
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'

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EyDu
User
Beiträge: 4868
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Mittwoch 1. April 2009, 14:54

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

Beitragvon str1442 » Mittwoch 1. April 2009, 15:02

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

Beitragvon Zap » Donnerstag 2. April 2009, 10:55

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Donnerstag 2. April 2009, 13:56

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

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder