在 Haskell 中我们有异步异常;我们可以使用throwTo
在另一个线程中引发任何异常:
throwTo :: Exception e => ThreadId -> e -> IO ()
throwTo
raises an arbitrary exception in the target thread (GHC only).
为了能够编写带有“获取锁后总是释放锁”这样的保证的代码,我们有mask
运行仅在计算阻塞时才能接收到异步异常的代码:
mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Executes an IO computation with asynchronous exceptions masked. That is, any thread which attempts to raise an exception in the current thread with
throwTo
will be blocked until asynchronous exceptions are unmasked again.
和更强的uninterruptibleMask
在屏蔽计算期间根本不会引发异步异常:
uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Like
mask
, but the masked computation is not interruptible
掩码用于实现更高级别的抽象,如 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
When you want to acquire a resource, do some work with it, and then release the resource, it is a good idea to use
bracket
, becausebracket
will install the necessary exception handler to release the resource in the event that an exception is raised during the computation. If an exception is raised, thenbracket
will re-raise the exception (after performing the release).
如果我理解正确的话,Python 有一种(不太通用的)异步异常形式,最显着的表现形式是 KeyboardInterrupt
。 :
Raised when the user hits the interrupt key (normally Control-C or Delete). During execution, a check for interrupts is made regularly.
文档对于何时可能发生“检查中断”并不准确,但它似乎暗示 KeyboardInterrupt
可能会在程序执行的任何点引发.因此,Python 的异步异常似乎在维护正确性方面同样存在微妙的困难。
例如,考虑这样的模式:
x = None
try:
x = acquire()
do_something(x) # (1)
finally:
if x is not None: # (2)
release(x)
如果在 (1)
期间出现任何异常,那么我们可以确信 finally
的内容 block 将被执行。但是如果 KeyboardInterrupt
在 (2)
期间会发生什么?
在没有屏蔽异步异常的情况下,似乎根本不可能保证资源清理。是否有一些设施,或者我们依赖 ostrich algorithm ?
最佳答案
这就是上下文管理器的用途。
with acquire() as x:
do_something(x)
acquire
返回一个对象,其类型定义了一个 __enter__
方法,该方法返回绑定(bind)到 x
的值,以及一个 __exit__
方法,在 with
语句结束时执行,无论该语句如何退出。
关于python - Python 是否具有与 Haskell 的 'mask' 或 'bracket' 函数等效的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42167862/