Chr*_*tin 12 python haskell asynchronous exception-handling
在Haskell中,我们有异步异常; 我们可以用来throwTo
在另一个线程中引发任何异常:
Run Code Online (Sandbox Code Playgroud)throwTo :: Exception e => ThreadId -> e -> IO ()
throwTo
在目标线程中引发任意异常(仅限GHC).
为了能够使用诸如"在获取锁之后总是释放锁"这样的保证来编写代码,我们必须mask
运行代码,其中只有在计算阻塞时才能接收异步异常:
Run Code Online (Sandbox Code Playgroud)mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
执行带有异步异常屏蔽的IO计算.也就是说,任何尝试在当前线程中引发异常的线程
throwTo
都将被阻塞,直到再次取消屏蔽异步异常.
和更强的uninterruptibleMask
在异步异常将不会引发在所有屏蔽的计算过程:
Run Code Online (Sandbox Code Playgroud)uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
喜欢
mask
,但掩盖的计算是不可中断的
掩码用于实现更高级别的抽象,例如bracket
:
Run Code Online (Sandbox Code Playgroud)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
:
当用户按下中断键(正常Control- C或Delete)时触发.在执行期间,定期检查中断.
关于何时可能发生"检查中断"的文档是不确定的,但似乎暗示KeyboardInterrupt
可以在程序执行的任何时刻引发a.因此,似乎Python的异步异常伴随着保持正确性的所有相同的微妙困难.
例如,考虑这样的模式:
x = None
try:
x = acquire()
do_something(x) # (1)
finally:
if x is not None: # (2)
release(x)
Run Code Online (Sandbox Code Playgroud)
如果在此期间引发任何异常(1)
,那么我们可以确保finally
将执行该块的内容.但如果a KeyboardInterrupt
期间会发生什么(2)
?
似乎根本不可能在存在asyc异常的情况下保证资源清理,而无法掩盖它们.是否有一些设施,或者我们依靠鸵鸟算法?
这就是上下文管理器的用途。
with acquire() as x:
do_something(x)
Run Code Online (Sandbox Code Playgroud)
acquire
返回一个对象,该对象的类型定义了一个__enter__
方法,该方法返回绑定到 的值x
,以及一个__exit__
方法,该方法在语句末尾执行with
,无论语句如何退出。