[Erledigt] Probleme mit Exceptions

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
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Mahlzeit! :)

Ich habe zwei Probleme mit Exceptions:
- Ich möchte bestimmte Exceptions besonders behandeln und
- ich möchte eine Exception zweimal werfen können (sieht wie ein Bug aus, ich habe aber keine Vorstellung, wo ich ihn versteckt haben könnte).

Hier der Code:

Code: Alles auswählen


#-----------------------------------------------------------------------------
class SpecException(Exception):

    EX_1 = 1
    EX_2 = 2
    #-------------------------------------------------------------------------
    def __init__(self, expression, message):
        print " Expression: %d" % expression
        print " Message   : " +  message
    #-------------------------------------------------------------------------

#-----------------------------------------------------------------------------
def testFunc1():
    raise SpecException( SpecException.EX_1, "BlaBla_1")

#-----------------------------------------------------------------------------
def testFunc2():
    raise SpecException( SpecException.EX_2, "BlaBla_2")

#-----------------------------------------------------------------------------

print "===================== Teil 1 ======================="
try:
    testFunc1()
except SpecException, SpecException.EX_1:
    print "Exception geschmissen!"
print "===================== Teil 2 ======================="
try:
    testFunc2()
except SpecException, SpecException.EX_1:
    print "Exception geschmissen!"
finally:
    print "Exception nicht behandelt!"


print "===================== Teil 3 ======================="
try:
    testFunc1()
except SpecException, SpecException.EX_1:
    print "Exception geschmissen!"


So weit, so einfach. Doch leider funzt da was nicht, wie ich erwartet habe. Die Ausgabe für Teil 1 und 2 ist die folgende:

Code: Alles auswählen


===================== Teil 1 =======================
 Expression: 1
 Message   : BlaBla_1
Exception geschmissen!
===================== Teil 2 =======================
 Expression: 2
 Message   : BlaBla_2
Exception geschmissen!
Exception nicht behandelt!

Wieso wird in Teil 2 der "execpt:" Zweig betreten? Der Wert der Exception ist doch 2 und nicht 1.

Weiter mit der zweiten Frage. Die gesamte Ausgabe ist die folgende:

Code: Alles auswählen


===================== Teil 1 =======================
 Expression: 1
 Message   : BlaBla_1
Exception geschmissen!
===================== Teil 2 =======================
 Expression: 2
 Message   : BlaBla_2
Exception geschmissen!
Exception nicht behandelt!
===================== Teil 3 =======================

Traceback (most recent call last):
  File "D:/PythonTest/Exception.py", line 46, in <module>
    testFunc1()
  File "D:/PythonTest/Exception.py", line 22, in testFunc1
    raise SpecException( SpecException.EX_1, "BlaBla_1")
  File "D:/PythonTest/Exception.py", line 16, in __init__
    super( SpecException, self).__init__(expression, message)
  File "D:/PythonTest/Exception.py", line 5, in __init__
    print " Expression: %d" % expression
TypeError: int argument required

Das versteh ich überhaupt nicht. Wieso wird beim zweiten Aufruf von testFunc1() nicht die '1' übergeben, sondern (wie der Eclipse debugger mir verraten hat) eine Instanz der SpecException?

Gruß und Danke,

Christoph
Zuletzt geändert von ChrisGTJ am Donnerstag 27. September 2007, 13:16, insgesamt 1-mal geändert.
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Noch ein Nachtrag: Wenn ich die Funktion testFunc1() wie folgt ändere:

Code: Alles auswählen

def testFunc1():
    raise SpecException( 1, "BlaBla_1")
dann funtioniert der zweite Teil wie erwartet. Auf das Problem der fehlenden Unterscheidung hat das jedoch keinen Einfluß.
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Ich zitiere mal aus http://docs.python.org/ref/try.html:
When a matching except clause is found, the exception is assigned to the target specified in that except clause, if present, and the except clause's suite is executed.
In Deinem Beispiel

Code: Alles auswählen

except SpecException, SpecException.EX_1:
wird also die geworfene Exception SpecException.EX_1 zugewiesen. Das ist vermutlich nicht das, was Du möchtest.
https://www.xing.com/go/invite/18513630.6a91d4
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

lutz.horn hat geschrieben:Ich zitiere mal aus http://docs.python.org/ref/try.html:
When a matching except clause is found, the exception is assigned to the target specified in that except clause, if present, and the except clause's suite is executed.
In Deinem Beispiel

Code: Alles auswählen

except SpecException, SpecException.EX_1:
wird also die geworfene Exception SpecException.EX_1 zugewiesen. Das ist vermutlich nicht das, was Du möchtest.
Richtig. Wie ich sehe, habe ich die Exception nicht verstanden.

Ok, dann ist das also die Lösung für mein Problem:

Code: Alles auswählen

#-----------------------------------------------------------------------------
class SpecException(Exception):

    EX_1 = 1
    EX_2 = 2
    #-------------------------------------------------------------------------
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
        print " Expression: %d" % expression
        print " Message   : " +  message
    #-------------------------------------------------------------------------

#-----------------------------------------------------------------------------
def testFunc1():
    raise SpecException( SpecException.EX_1, "BlaBla_1")

#-----------------------------------------------------------------------------
def testFunc2():
    raise SpecException( SpecException.EX_2, "BlaBla_2")

#-----------------------------------------------------------------------------

print "===================== Teil 1 ======================="

try:
    testFunc1()
except SpecException, e:
    if e.expression == SpecException.EX_1:
        print "Exception geschmissen!"
else:
    print "Teil 1, else"
    
print "===================== Teil 2 ======================="
try:
    testFunc2()
except SpecException, e:
    if e.expression == SpecException.EX_1:
        print "Exception 1 geschmissen!"
    else:
        print "Andere Exception geworfen"

print "===================== Teil 3 ======================="
try:
    testFunc1()
except SpecException, e:
    if e.expression == SpecException.EX_1:
        print "Exception geschmissen!"

Vielen Dank Lutz.Horn für Deinen Hinweis!

Christoph
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Wenn du Exceptions unterschiedlich behandeln willst, muessen sie Instanzen unterschiedlicher Klassen sein. In deinem Fall z.B.:

Code: Alles auswählen

class SpecException(Exception):
    pass

class SpecException1(SpecException):
    pass

class SpecException2(SpecException):
    pass

Dann kannst du entweder nur eine Exception-Art abfangen mit:

Code: Alles auswählen

try:
    ...
except SpecException1:
    ...
oder beide, indem du die Eltern-Klasse angibst. Du kannst nicht schon in dem except-Ausdruck auf Attribute der Exception zugreifen, erst im nachfolgenden Block:

Code: Alles auswählen

...
except MyException, e:
    print e.myattribute
Und der finally-Block wird *immer* ausgefuehrt.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
ChrisGTJ
User
Beiträge: 105
Registriert: Mittwoch 22. August 2007, 15:45

Danke für die Info, Rebecca.

Wenn ich nur einen bestimmten Teil der Exception behandeln will, den Rest aber an anderen Orten, dann müßte ich es wohl so machen:

Code: Alles auswählen

except SpecException, ex:
    if ex.expression == SpecException.EX_1:
        mach_das()
    else:
        raise ex

Gruß,

Christoph
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Entweder `raise ex` oder `raise`. Der Unterschied ist, dass im zweiten Fall der Handler nicht im Traceback auftaucht.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten