簡體   English   中英

在“try”或“except”塊之外的python函數末尾的“raise”

[英]“raise” at the end of a python function outside “try” or “except” block

如果raise不在tryexcept子句中,而只是作為函數中的最后一條語句,它有什么作用?

def foo(self):
    try:
        # some code that raises an exception
    except Exception as e:
        pass

    # notice that the "raise" is outside
    raise

此示例打印 1 但不打印 2,因此必須是最后一個raise語句僅引發最后一個拋出的異常。

def foo():
    try:
        raise Exception()
    except Exception as e:
        pass

    print 1
    raise
    print 2

if __name__ == '__main__':
    foo()

這種使用模式的任何官方文檔?

正如羅素所說,

一個裸raise語句重新引發最后一個捕獲的異常。

這是否發生在 try-except 塊中並不重要。 如果已捕獲異常,則調用raise將重新引發該異常。 否則,Python 會抱怨之前捕獲的異常是None並引發TypeError因為None不是實際可以引發的東西。

正如tdelaney所說,除非在錯誤處理函數中,否則這樣做似乎沒有意義。 我個人認為它甚至不屬於錯誤處理函數,因為raise應該仍然在except子句中。 無論是否發生錯誤,有人都可以使用它來嘗試執行代碼,但finally子句是執行此操作的正確方法。 另一種可能性是使用它來確定在執行函數時是否發生錯誤,但有更好的方法來做到這一點(例如返回一個額外的值來指示是否/哪里發生了錯誤)。

Bare raise 重新引發當前異常。 這通常在函數結束時沒有意義,除非函數在異常中被調用:

就其本身而言,raise 是無效的,python 會拋出自己的異常

>>> def x():
...     raise
>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in x
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType

但是如果在異常塊中調用,它會正常運行

>>> try:
...     int('a')
... except:
...     x()
... 
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>> 

編輯

如果函數正在嘗試某種恢復,這可能是完全合理的做法。 該函數可以修復損壞的內容、記錄消息、觸發滅火器等……如果它仍然認為系統有錯誤,則raise

一個裸raise語句重新引發最后一個捕獲的異常。 https://docs.python.org/2/tutorial/errors.html#rising-exceptions

從這個文檔我們可以讀到:

如果不存在表達式, raise 重新引發當前作用域中活動的最后一個異常。 如果當前范圍內沒有異常處於活動狀態,則會引發 TypeError 異常,表明這是一個錯誤(如果在 IDLE 下運行,則會引發 Queue.Empty 異常)。

這意味着,就您的代碼而言,如果在try ... except塊中沒有發生異常,那么您將迫使程序引發TypeError異常。

我遇到了這樣的問題,如果我的函數沒有返回值,我需要在 try/except 塊之外引發先前捕獲的異常。 我在systraceback模塊中做了一些環顧四周,但找不到一個好的方法來做到這一點,所以我最終將異常存儲在塊之外。

def foo():
    caught = None

    try:
        raise Exception
    except Exception as e:
        caught = e
        pass

    raise caught


f = foo()

輸出

Traceback (most recent call last):
  line 13, in <module>
  line 10, in foo
  line 5, in foo
Exception

很明顯,這在上面的例子中沒有用,但是如果你需要在循環中多次嘗試並重新加注,它非常有用。 我的具體需求是 HTTP 請求重試機制。

import time

def foo(key):
    caught = None
    
    for i in [1, 2, 3, 4, 5]:
        try:
            return d[key]
        except KeyError as e:
            caught = e
            print(i)
            time.sleep(i)
            continue

    raise caught

d = {"bar": "baz"}

f = foo(key="baz")

輸出

1
2
3
4
5
Traceback (most recent call last):
  line 19, in <module>
  line 15, in foo
  line 8, in foo
KeyError: 'baz'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM