Python协程中使用上下文

 在Python 3.7中,asyncio 协程加入了对上下文的支持。使用上下文就可以在一些场景下隐式地传递变量,比如数据库连接session等,而不需要在所有方法调用显示地传递这些变量。使用得当的话,可以提高接口的可读性和扩展性。

基本使用方式

协和的上下文是通过 contextvars 中的 ContextVar 对象来管理的。最基本的使用方式是在某一调用层次中设置上下文,然后在后续调用中使用。如下例所示:

import asyncio import contextvars from random import randint from unittest import TestCase  request_id_context = contextvars.ContextVar('request-id')   async def inner(x):     request_id = request_id_context.get()     if request_id != x:         raise AssertionError('request_id %d from context does NOT equal with parameter x %d' % (request_id, x))      print('start handling inner request-%d, with x: %d' % (request_id, x))     await asyncio.sleep(randint(0, 3))     print('finish handling inner request-%d, with x: %d' % (request_id, x))   async def outer(i):     print('start handling outer request-%d' % i)     request_id_context.set(i)     await inner(i)     print('finish handling outer request-%d with request_id in context %d' % (i, request_id_context.get()))   async def dispatcher():     await asyncio.gather(*[         outer(i) for i in range(0, 10)     ])   class ContextTest(TestCase):      def test(self):         asyncio.run(dispatcher())

上例中,在最后定义了一个单元测试用例对象 ContextTest 。它的方法 test 是程序的入口,使用 asyncio.run 方法来在协程中执行被测试的异步方法 dispatcher 。dispatcher 则并发启动10个异步方法 outer 。 outer方法首先将在模块层定义的上下文变量 request_id_context 设置为当前调用指定的值,这个值对于每个 outer 的调用都是不同的。 然后在后续被调用的 inner 方法,以及 outer 方法内部访问了这个上下文变更。在 inner 方法内容,则比较了显示传入的 i 和从上下文变量中取出的 request_id 。

测试用例的执行结果如下:

start handling outer request-0 start handling inner request-0, with x: 0 start handling 
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信