Python是否具有Haskell的"掩码"或"括号"功能?

Chr*_*tin 12 python haskell asynchronous exception-handling

在Haskell中,我们有异步异常; 我们可以用来throwTo在另一个线程中引发任何异常:

throwTo :: Exception e => ThreadId -> e -> IO ()
Run Code Online (Sandbox Code Playgroud)

throwTo 在目标线程中引发任意异常(仅限GHC).

为了能够使用诸如"在获取锁之后总是释放锁"这样的保证来编写代码,我们必须mask运行代码,其中只有在计算阻塞时才能接收异步异常:

mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Run Code Online (Sandbox Code Playgroud)

执行带有异步异常屏蔽的IO计算.也就是说,任何尝试在当前线程中引发异常的线程throwTo都将被阻塞,直到再次取消屏蔽异步异常.

和更强的uninterruptibleMask在异步异常将不会引发在所有屏蔽的计算过程:

uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Run Code Online (Sandbox Code Playgroud)

喜欢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
Run Code Online (Sandbox Code Playgroud)

当你想获取资源,做一些工作,然后释放资源时,最好使用bracket,因为bracket如果在计算过程中引发异常,将安装必要的异常处理程序来释放资源.如果引发异常,bracket则会重新引发异常(执行发布后).

如果我理解正确,Python有一种(不那么普遍的)异步异常形式,最显着的表现形式是KeyboardInterrupt:

当用户按下中断键(正常Control- CDelete)时触发.在执行期间,定期检查中断.

关于何时可能发生"检查中断"的文档是不确定的,但似乎暗示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异常的情况下保证资源清理,而无法掩盖它们.是否有一些设施,或者我们依靠鸵鸟算法

che*_*ner 4

这就是上下文管理器的用途。

with acquire() as x:
    do_something(x)
Run Code Online (Sandbox Code Playgroud)

acquire返回一个对象,该对象的类型定义了一个__enter__方法,该方法返回绑定到 的值x,以及一个__exit__方法,该方法在语句末尾执行with,无论语句如何退出。

  • 如果发生进一步的异常,可以中断 `__exit__` 方法吗? (3认同)