803 Stimmen

Welchen Zweck erfüllt die optionale "else"-Klausel der "try"-Anweisung in Python?

Was ist der Verwendungszweck der optionalen else Klausel des try Aussage?

5 Stimmen

Die meisten Antworten scheinen sich darauf zu konzentrieren, warum wir das Material in der else-Klausel nicht einfach in die try-Klausel selbst einfügen können. Die Frage stackoverflow.com/questions/3996329 fragt ausdrücklich, warum der Code der else-Klausel nicht gehen kann nach der Try-Block selbst, und diese Frage ist mit dieser hier verknüpft, aber ich sehe hier keine klare Antwort auf diese Frage. Ich glaube stackoverflow.com/a/3996378/1503120 beantwortet diese Frage in hervorragender Weise. Ich habe auch versucht, die verschiedenen Bedeutungen der einzelnen Klauseln zu erläutern stackoverflow.com/a/22579805/1503120 .

2 Stimmen

Wenn die Ausnahme nicht auslöst, soll vor der abschließenden Bereinigung etwas geschehen, das nicht selbst die gleiche Ausnahmebehandlung auslösen soll.

5 Stimmen

Nachdem ich vergessen hatte, was else tut in try/else y for/else Ich habe es mehrmals mit dem Begriff noexcept y nobreak in diesen jeweiligen Zusammenhängen. Ich persönlich halte es für eine so unglückliche Überfrachtung des Wortes, dass ich versuche, es nach Möglichkeit zu vermeiden, da es die Leute, die den Code lesen, dazu zwingt, sich zu fragen: "Was macht dieses Ding nochmal?" Normalerweise ist ein Flag, eine continue o break Aussage kann das, was ich ausdrücken will, mit wenigen zusätzlichen Zeilen, aber sicherlich mit mehr Klarheit wiedergeben (wenn die Popularität der Frage ein Hinweis darauf ist).

4voto

tzot Punkte 86792

Das war's. Der "else"-Block einer try-except-Klausel ist für Code vorgesehen, der ausgeführt wird, wenn (und nur wenn) die versuchte Operation erfolgreich ist. Er kann verwendet werden, und er kann missbraucht werden.

try:
    fp= open("configuration_file", "rb")
except EnvironmentError:
    confdata= '' # it's ok if the file can't be opened
else:
    confdata= fp.read()
    fp.close()

# your code continues here
# working with (possibly empty) confdata

Ich persönlich mag sie und verwende sie, wenn es angebracht ist. Es gruppiert Aussagen semantisch.

4voto

vadimbog Punkte 386

Ich würde einen weiteren Anwendungsfall hinzufügen, der bei der Handhabung von DB-Sitzungen einfach erscheint:

    # getting a DB connection 
    conn = db.engine.connect()

    # and binding to a DB session
    session = db.get_session(bind=conn)

    try:
        # we build the query to DB
        q = session.query(MyTable).filter(MyTable.col1 == 'query_val')

        # i.e retrieve one row
        data_set = q.one_or_none()

        # return results
        return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]

    except:
        # here we make sure to rollback the transaction, 
        # handy when we update stuff into DB
        session.rollback()
        raise

    else:
        # when no errors then we can commit DB changes
        session.commit()

    finally:
        # and finally we can close the session
        session.close()

3 Stimmen

Mir scheint, wie es nur nützlich ist, wenn Sie mit finally, sonst können Sie nur die else-Code außerhalb der Try-Bereich setzen

2voto

DevPlayer Punkte 5017

Vielleicht wäre das eine Möglichkeit:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

Vielleicht finden Sie dadurch eine Verwendung.

2voto

grdvnl Punkte 628

Hier ist eine weitere Stelle, an der ich dieses Muster gerne verwende:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`

1 Stimmen

Sie können einfach Folgendes verwenden continue stattdessen das Muster des "frühen Ausbruchs". Dadurch können Sie die "else"-Klausel und ihre Einrückung weglassen, wodurch der Code leichter zu lesen ist.

2voto

sirlark Punkte 2137

Ich habe die try: ... else: Konstrukt nützlich, wenn Sie Datenbankabfragen durchführen und die Ergebnisse dieser Abfragen in einer separaten Datenbank desselben Typs protokollieren. Nehmen wir an, ich habe viele Worker-Threads, die alle Datenbankabfragen in einer Warteschlange verarbeiten

#in a long running loop
try:
    query = queue.get()
    conn = connect_to_db(<main db>)
    curs = conn.cursor()
    try:
        curs.execute("<some query on user input that may fail even if sanitized">)
    except DBError:
        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of failed query")
        logcurs.close()
        logconn.close()
    else:

        #we can't put this in main try block because an error connecting
        #to the logging DB would be indistinguishable from an error in 
        #the mainquery 

        #We can't put this after the whole try: except: finally: block
        #because then we don't know if the query was successful or not

        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of successful query")
        logcurs.close()
        logconn.close()
        #do something in response to successful query
except DBError:
    #This DBError is because of a problem with the logging database, but 
    #we can't let that crash the whole thread over what might be a
    #temporary network glitch
finally:
    curs.close()
    conn.close()
    #other cleanup if necessary like telling the queue the task is finished

Wenn Sie natürlich zwischen den möglichen Ausnahmen, die ausgelöst werden könnten, unterscheiden können, müssen Sie dies nicht verwenden, aber wenn Code, der auf ein erfolgreiches Codestück reagiert, dieselbe Ausnahme auslösen könnte wie das erfolgreiche Stück, und Sie können die zweite mögliche Ausnahme nicht einfach durchgehen lassen oder bei Erfolg sofort zurückkehren (was in meinem Fall den Thread beenden würde), dann ist dies sehr nützlich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X