阿布云

你所需要的,不仅仅是一个好用的代理。

python的黑魔法---上下文管理器(contextor)(二)

阿布云 发表于

原文出处: 人间世   

上下文管理器工具

通过实现上下文协议定义创建上下文管理器很方便,Python为了更优雅,还专门提供了一个模块用于实现更函数式的上下文管理器用法.

图片1.png

使用contextlib 定义一个上下文管理器函数,通过with语句,database调用生成一个上下文管理器,然后调用函数隐式的__enter__方法,并将结果通yield返回.最后退出上下文环境的时候,在excepit代码块中执行了__exit__方法.当然我们可以手动模拟上述代码的执行的细节.

图片2.png

上下文管理器的用法

既然了解了上下文协议和管理器,当然是运用到实践啦.通常需要切换上下文环境,往往是在多线程/进程这种编程模型.当然,单线程异步或者协程的当时,也容易出现函数的上下文环境经常变动.

异步式的代码经常在定义和运行时存在不同的上下文环境.此时就需要针对异步代码做上下文包裹的hack.看下面一个例子:

图片3.png

主函数中main中,定义了异步任务函数async_task的调用.async_task中异常,在except中很容易catch,可是callback中出现的异常,则无法捕捉.原因就是定义的时候上下文为当前的线程执行环境,而使用了tornado的ioloop.add_callback方法,注册了一个异步的调用.当callback异步执行的时候,他的上下文已经和async_task的上下文不一样了.因此在main的上下文,无法catch异步中callback的异常.

下面使用上下文管理器包装如下:

图片4.png

可见,callback的函数的异常,在上下文管理器Contextor中被处理了,也就是说callback调用的时候,把之前main的上下文保存并传递给了callback.当然,上述的代码也可以改写如下:

图片5.png

效果类似.