2016-07-20 5 views
2

Ziel: Ich habe mehrere Zeilen Code, die jeweils die gleiche Art von Fehler erzeugen können, und die gleiche Art von Antwort zu gewährleisten. Wie verhindere ich das Problem "Wiederhole nicht selbst" mit den try-except-Blöcken.Ein DRY-Ansatz für Python-try-except-Blöcke?

Hintergrund:

ich Regex schlecht zu kratzen formatierte Daten aus einer Textdatei, und geben Sie in das Feld eines benutzerdefinierten Objekts. Der Code funktioniert hervorragend, außer wenn das Feld leer gelassen wurde. In diesem Fall wird ein Fehler ausgegeben.

Ich handle diesen Fehler in einem Versuch-außer-Block. Wenn ein Fehler auftritt, fügen Sie ein Leerzeichen in das Feld des Objekts ein (d. H. "").

Das Problem ist, es wird leicht lesbar, schön, Python-Code in ein Durcheinander von Versuch-außer Blöcke, die jeweils die gleiche Sache. Dies ist ein Verstoß gegen "sich nicht selbst wiederholen" (a.k.a. DRY).

Der Code:

Bevor:

sample.thickness = find_field('Thickness', sample_datum)[0] 
sample.max_tension = find_field('Maximum Load', sample_datum)[0] 
sample.max_length = find_field('Maximum Extension', sample_datum)[0] 
sample.test_type = sample_test 

Nach:

try: 
    sample.thickness = find_field('Thickness', sample_datum)[0] 
except: 
    sample.thickness = '' 

try: 
    sample.max_tension = find_field('Maximum Load', sample_datum)[0] 
except: 
    sample.max_tension = '' 

try: 
    sample.max_length = find_field('Maximum Extension', sample_datum)[0] 
except: 
    sample.max_length = '' 

try:  
    sample.test_type = sample_test 
except: 
    sample.test_type = '' 

Was ich brauche:

Gibt es eine pythonische Art, dies zu schreiben? Irgendein Block, wo ich sagen kann, wenn es einen Index-außerhalb-des-Bereichs-Fehlers bei irgendeiner dieser Linien gibt (anzeigend, dass das Feld leer war und ReGex nichts zurückgeben konnte) füge ein Leerzeichen in das Beispielfeld ein.

+0

Welche Art von Fehler wirft es? –

+0

Ein out-of-Index. Die Suchfeldfunktion gibt eine Liste der ReGex-Suchergebnisse zurück. Wenn ReGex nichts findet, ist die zurückgegebene Liste leer. Wenn ich versuche, das erste Ergebnis zu erhalten, bekomme ich diese Ausnahme. –

+1

Wenn man darüber nachdenkt, ist die Antwort auf dieses spezielle Problem trivial. Ändern Sie die Funktion 'find_field()', um bei einer fehlgeschlagenen ReGex-Suche ein Leerzeichen zu erhalten. Ich hatte jedoch ähnliche Programmierprobleme, daher bleibt die Antwort auf diese Frage für andere relevant. –

Antwort

5

Was ist mit Refactoring einer Funktion daraus?

def maybe_find_field(name, datum): 
    try: 
     return find_field(name, datum)[0] 
    except IndexError: # Example of specific exception to catch 
     return '' 

sample.thickness = maybe_find_field('Thickness', sample_datum) 
sample.max_tension = maybe_find_field('Maximum Load', sample_datum) 
sample.max_length = maybe_find_field('Maximum Extension', sample_datum) 
sample.test_type = sample_test 

BTW, nicht einfach alle möglichen Ausnahmen mit except: fangen, es sei denn, das ist wirklich das, was Sie tun möchten. Alles abzufangen kann einen Implementierungsfehler verbergen, der später schwierig zu debuggen ist. Wann immer Sie können, binden Sie Ihren Fall except an die spezifische Ausnahme, die Sie benötigen.

0

Sie können beliebig viele except Blöcke haben, die verschiedene Arten von Ausnahmen behandeln. Es ist auch nichts falsch daran, mehrere Anweisungen im selben try/catch-Block zu haben.

try: 
    doMyDangerousThing() 
except ValueError: 
    print "ValueError!" 
except HurrDurrError: 
    print "hurr durr, there's an error" 

try: 
    doMyDangerousThing() 
    doMySecondDangerousThing() 
except: 
    print "Something went wrong!" 
+0

Während ich dankbar für Ihr Feedback bin, fühle ich, dass diese Antwort den gesamten Punkt der Frage verfehlt. Ich habe keine Notwendigkeit, verschiedene Ausnahmen anders zu behandeln (tatsächlich erzeugt jeder Fehler ein Leerzeichen), sondern fragte, wie ich Code aufräumen könnte, in dem es eine Reihe von fast identischen try-except-Blöcken gab. –

1

Wenn Sie sich wiederholen Code finden, kapseln Sie es in einer Funktion. In diesem Fall erstellen Sie eine Funktion, die die Ausnahme für Sie behandelt.

def try_find_field(field_name, datum, default_value): 
    try: 
     return find_field(field_name, datum)[0] 
    except: 
     return default_value