第三章:算法-contextlib:上下文管理器工具-动态上下文管理器栈-任意上下文回调

3.4.7.2 任意上下文回调
ExitStack还支持关闭上下文的任意回调,从而可以狠容易地清理不通过上下文管理器控制的资源。

import contextlib

def callback(*args,**kwds):
    print('closing callback({},{})'.format(args,kwds))

with contextlib.ExitStack() as stack:
    stack.callback(callback,'arg1','arg2')
    stack.callback(callback,arg3='val3')

与完整上下文管理器的__exit__()方法一样,这些回调会按其注册的逆序调用。
运行结果:

closing callback((),{‘arg3’: ‘val3’})
closing callback((‘arg1’, ‘arg2’),{})

不论是否出现错误,都会调用这些回调,而且不会为它们提供是否出现错误的任何信息。其返回值将被忽略。

import contextlib

def callback(*args,**kwds):
    print('closing callback({},{})'.format(args,kwds))

try:
    with contextlib.ExitStack() as stack:
        stack.callback(callback,'arg1','arg2')
        stack.callback(callback,arg3='val3')
        raise RuntimeError('throw error')
except RuntimeError as err:
    print('ERROR:{}'.format(err))

由于回调不能访问错误,所以它们无法防止异常在上下文管理器栈中继续传播。
运行结果:

closing callback((),{‘arg3’: ‘val3’})
closing callback((‘arg1’, ‘arg2’),{})
ERROR:throw error

回调提供了一种便捷的方式来清晰地定义清理逻辑,而没有创建新上下文管理器类的开销。为了提高代码的可读性,这个逻辑可以被封装到一个内联函数中,callback()可以作为一个修饰符。

import contextlib

with contextlib.ExitStack() as stack:
    @stack.callback
    def inline_cleanup():
        print('inline_cleanup()')
        print('local_resource = {!r}'.format(local_resource))

    local_resource = 'resource created in context'
    print('within the context')

没有办法为使用callback()修饰符注册的函数指定参数。不过,如果清理回调采用内联方式定义,那么根据作用域规则,他就可以访问调用代码中定义的变量。
运行结果:

within the context
inline_cleanup()
local_resource = ‘resource created in context’

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值