在Haskell中,我們有異步異常;我們可以用throwTo
提出任何例外在另一個線程:Python是否與Haskell的'mask'或'bracket'函數等價?
throwTo :: Exception e => ThreadId -> e -> IO()
throwTo
提出的目標線程的任意異常(僅GHC)。
爲了能夠與像「收購之後總是會釋放鎖」保證編寫的代碼,我們必須mask
運行代碼,其中在計算阻塞異步異常可能只收到:
mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
使用異步異常執行IO計算屏蔽了。也就是說,任何嘗試在
throwTo
當前線程中引發異常的線程都將被阻塞,直到異步異常再次取消屏蔽。
和更強的uninterruptibleMask
在異步異常情況將不是一個蒙面的計算過程中引發的在所有:
uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
像
mask
,但蒙面計算是不可中斷
掩蔽用於實現更高層次的抽象,如bracket
:
bracket :: IO a -- computation to run first ("acquire resource") -> (a -> IO b) -- computation to run last ("release resource") -> (a -> IO c) -- computation to run in-between -> IO c -- returns the value from the in-between computation
當你想要獲取的資源,做一些工作吧,然後釋放資源,它是用
bracket
,因爲bracket
將安裝必要的異常處理程序來釋放資源是一個好主意在計算過程中發生異常的情況下。如果發生異常,則bracket
將重新引發異常(執行發佈後)。
如果我理解正確,Python有異步異常的(小於一般)的形式,最顯着的表現是KeyboardInterrupt
:
當用戶點擊中斷鍵提高(通常控制 - C或刪除)。在執行期間,會定期檢查中斷。
的文檔是不精確的約當「檢查有無中斷」可能發生,但它似乎暗示着KeyboardInterrupt
可以提高在程序執行任何點。因此,看起來,Python的異步異常具有保持正確性的所有相同的微妙困難。
例如,請考慮這樣一個規律:
x = None
try:
x = acquire()
do_something(x) # (1)
finally:
if x is not None: # (2)
release(x)
如果有任何異常被(1)
提高,那麼我們放心,finally
塊的內容將被執行。但是如果KeyboardInterrupt
在(2)
期間會發生什麼?
在沒有掩蓋它們的情況下,在存在asyc異常的情況下保證資源清理似乎根本不可能。有沒有這方面的設施,還是我們依靠ostrich algorithm?
我想你幾乎必須爲Ctrl-C安裝自己的信號處理程序,如果你想這樣做。 – user2357112