2013-08-01 8 views
14

documentation dla instrukcji raise bez argumentów mówiprzebicie bez argumentu

If no expressions are present, raise re-raises the last exception that was active in the current scope.

Kiedyś myślałem, że oznaczało, że obecna funkcja należało wykonanie klauzuli except. Po przeczytaniu this question i eksperymentowaniu trochę, myślę, że oznacza to, że każda funkcja na stosie musi być wykonana klauzula except, ale nie jestem pewien. Również mam sobie sprawę, że nie ma pojęcia, w jaki sposób działa ślad stosu z podbiciem no-Arg

def f(): 
    try: 
    raise Exception 
    except: 
    g() 

def g(): 
    raise 

f() 

produkuje

Traceback (most recent call last): 
    File "foo", line 10, in <module> 
    f() 
    File "foo", line 5, in f 
    g() 
    File "foo", line 3, in f 
    raise Exception 
Exception 

To nie wygląda na stosie w czasie podbicie początkowe lub stos w momencie ponownego przebicia lub łączenie obu stosów lub cokolwiek co mogę zrozumieć.

Mam rację co do podbicia bez argonu, szukającego jakiejkolwiek funkcji na stosie, wykonującej klauzulę except? Ponadto, jak działa śledzenie stosu przy przebiciu?

+0

Dobre pytanie! – Marcin

+0

Warto zauważyć, że wszystkie te rzeczy zostały wyczyszczone - i znacznie lepiej udokumentowane - w Pythonie 3.x. Możesz więc o wiele lepiej spojrzeć na 3.3 niż 2.7. (IIRC, samo sformułowanie dla 'raise' nie jest dużo lepsze, ale pojęcie" aktywnego wyjątku "jest faktycznie zdefiniowane gdzieś lub w innym miejscu, więc po prostu musisz je wyszukać zamiast próbować odgadnąć jego znaczenie ...) – abarnert

Odpowiedz

11

Kiedy raise bez argumentów, interpreter poszukuje wyjątkiem ostatni podniesiony i obsługiwane. Działa to tak samo, jak w przypadku użycia najnowszego typu wyjątku, wartości i śledzenia za pomocą raise.

To jest przechowywane w stanie interpretatora dla bieżącego wątku, a te same informacje można pobrać za pomocą sys.exc_info(). Przez "obsługiwane" mam na myśli to, że klauzula except uchwyciła wyjątek. Cytowanie try statement documentation:

Before an except clause’s suite is executed, details about the exception are assigned to three variables in the sys module: sys.exc_type receives the object identifying the exception; sys.exc_value receives the exception’s parameter; sys.exc_traceback receives a traceback object (see section The standard type hierarchy identifying the point in the program where the exception occurred. These details are also available through the sys.exc_info() function, which returns a tuple (exc_type, exc_value, exc_traceback) .

Zobacz implemenation notes w pętli ocena Python (kod C), w szczególności:

The second bullet was for backwards compatibility: it was (and is) common to have a function that is called when an exception is caught, and to have that function access the caught exception via sys.exc_ZZZ. (Example: traceback.print_exc()).

traceback odzwierciedla, jak przyszedł do re-raise dokładnie. Obecny stos (linia 10 wywołująca f(), linia 5 wywołująca g()) oraz oryginalna lokalizacja wyjątku podniesiona: linia 3.

+0

Myślę, że nie może być dobrze, ale wygląda na to, że stan wyjątku jest inaczej traktowany w trybie interaktywnym niż podczas wykonywania skryptu. Umieszczenie przebicia po klauzuli except działa inaczej w funkcji lub skrypcie niż na najwyższym poziomie w sesji interaktywnej. – user2357112

+0

@ user2357112: Nie, nie ma. Informacje * o śledzeniu * są rzadkie, ponieważ nie ma kodu źródłowego do introspekcji i dołączania, ale numery wierszy są dokładnie takie same. –

+0

Naprawdę? Ponieważ gdy go wypróbuję, przechwycenie wyjątku i próba jego zmiany po usunięciu klauzuli except powoduje, że wyjątki muszą być klasami starego typu lub wywodzić się z BaseException, a nie NoneType' na najwyższym poziomie sesji interaktywnej, ale z powodzeniem powtórzy poprzedni błąd, kiedy umieściłem go w skrypcie lub funkcji. – user2357112

Powiązane problemy