asyncio之异步上下文管理器
异步上下文管理器
前面文章我们提到了上下文管理器,但是这个上下文管理器只适用于同步代码,不能用于异步代码(async def形式),不过不用担心今天我们就来讨论在异步中如何使用上下文管理器。
特别提醒本教程所使用的Python版本为Python3.7。
async with
异步上下文管理器。类似于同步上下文管理器,我们知道使用with可以实现一个上下文管理的器,而对于异步上下文管理器其根本表现形式为async with,下面的一段代码告诉你async with是如何运作的。
import asyncio
class AContext:
def __init__(self):
print("in init")
async def __aenter__(self):
print("in aenter")
async def __aexit__(self, exc_type, exc_val, exc_tb):
print("in aexit")
async def main():
async with AContext() as ac:
print("in with", ac)
if __name__ == '__main__':
print("start")
asyncio.run(main())
输出内容
start
in init
in aenter
in with None
in aexit
下面说下async with和with的不同地方
语法上,with实现了enter和exit两个方法,async with实现了类似方法
aenter和aexit在同步的基础上加个a,实际上就是代表asynchronous。
实现上,使用普通的函数就可以实现with,但是async with需要通过异步函数的形式去实现,就像上面的例子一样。
asynccontextmanager
从Python 3.7开始,有两种方法可以编写异步上下文管理器。一种就是前面提到的魔法函数的实现,另外一种就是contextlib的另外一个模块asynccontextmanager。通过装饰器的方式实现一个异步上下文管理器
import asyncio
from contextlib import asynccontextmanager
from concurrent.futures.thread import ThreadPoolExecutor
class AsyncFile(object):
def __init__(self, file, loop=None, executor=None):
if not loop:
loop = asyncio.get_running_loop() # 获取当前运行事件循环
if not executor:
executor = ThreadPoolExecutor(10) # 线程池数量10
self.file = file
self.loop = loop
self.executor = executor
self.pending = []
self.result = []
def write(self, string):
"""
实现异步写操作
:param string: 要写的内容
:return:
"""
self.pending.append(
self.loop.run_in_executor(
self.executor, self.file.write, string,
)
)
def read(self, i):
"""
实现异步读操作
:param i:
:return:
"""
self.pending.append(
self.loop.run_in_executor(self.executor, self.file.read, i,)
)
def readlines(self):
self.pending.append(
self.loop.run_in_executor(self.executor, self.file.readlines, )
)
@asynccontextmanager
async def async_open(path, mode="w"):
with open(path, mode=mode) as f:
loop = asyncio.get_running_loop()
file = AsyncFile(f, loop=loop)
try:
yield file
finally:
file.result = await asyncio.gather(*file.pending, loop=loop)
上面的代码通过使用asyncio中run_in_executor运行一个线程,来使得阻塞操作变为非阻塞操作,达到异步非阻塞的目的。
AsyncFile类提供了一些方法,这些方法将用于将write、read和readlines的调用添加到pending列表中。这些任务通过finally块中的事件循环在ThreadPoolExecutor进行调度。
yield 前半段用来表示_aenter_()
yield 后半段用来表示_aexit_()
使用finally以后可以保证链接资源等使用完之后能够关闭。
运行异步上下文管理器
如果调用前面示例中的异步上下文管理器,则需要使用关键字async with来进行调用。另外带有async with的语句只能在异步函数中使用。
from asynciodemo.asyncwith import async_open
import asyncio
import tempfile
import os
async def main():
tempdir = tempfile.gettempdir()
path = os.path.join(tempdir, "run.txt")
print(f"临时文件目录:{path}")
async with async_open(path, mode='w') as f:
f.write("公众号: ")
f.write("Python")
f.write("学习")
f.write("开发")
if __name__ == '__main__':
asyncio.run(main())
使用方法和with类似可以通过使用as,然后使用其句柄,唯一需要注意的就是要在异步函数中使用。
同步任务
在之前的一些异步教程里和大家说了关于协程中的几个同步方法,asyncio.wait和asyncio.gather,这里我们可以配合这些方法通过异步上下文管理器来实现同步任务,请看如下代码
import asyncio
# 同步挂起协程
class Sync():
def __init__(self):
self.pending = []
self.finished = None
def schedule_coro(self, coro, shield=True):
#如果去掉asyncio.shield,在取消fut函数的时候,就会导致coro协程也出错。
fut = asyncio.shield(coro) if shield else asyncio.ensure_future(coro)
self.pending.append(fut)
return fut
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
# 退出async with的时候,任务列表中的任务进行并发操作。
self.finished = await asyncio.gather(*self.pending, return_exceptions=True)
async def workload1():
await asyncio.sleep(2)
print("These coroutines will be executed return 41")
return 41
async def workload2():
await asyncio.sleep(2)
print("These coroutines will be executed return 42")
return 42
async def workload3():
await asyncio.sleep(2)
print("These coroutines will be executed return 43")
return 43
async def main():
async with Sync() as sync:
# 使用异步上下文可以创建同步协程程序
sync.schedule_coro(workload1())
sync.schedule_coro(workload2())
sync.schedule_coro(workload3())
print("All scheduled corotines have retuned or throw:", sync.finished)
if __name__ == '__main__':
asyncio.run(main())
输出
These coroutines will be executed return 41
These coroutines will be executed return 42
These coroutines will be executed return 43
All scheduled corotines have retuned or throw: [41, 42, 43]
1.程序是同步的形式并发输出的。
2. schedule_coro的作用是将协程workload1,workload2,workload3添加到任务列表pending,退出async with的时候,任务列表中的任务进行并发操作。
asyncio之异步上下文管理器的更多相关文章
- 深入Asyncio(七)异步上下文管理器
Async Context Managers: async with 在某些场景下(如管理网络资源的连接建立.断开),用支持异步的上下文管理器是很方便的. 那么如何理解async with关键字? 先 ...
- python 黑魔法 ---上下文管理器(contextor)
所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...
- (转)Python中的上下文管理器和Tornado对其的巧妙应用
原文:https://www.binss.me/blog/the-context-manager-of-python-and-the-applications-in-tornado/ 上下文是什么? ...
- Python 上下文管理器模块--contextlib
在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...
- Python 的上下文管理器是怎么设计的?
花下猫语:最近,我在看 Python 3.10 版本的更新内容时,发现有一个关于上下文管理器的小更新,然后,突然发现上下文管理器的设计 PEP 竟然还没人翻译过!于是,我断断续续花了两周时间,终于把这 ...
- python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)
0.关于上下文管理器上下文管理器是可以在with语句中使用,拥有__enter__和__exit__方法的对象. with manager as var: do_something(var) 相当于以 ...
- 翻译《Writing Idiomatic Python》(五):类、上下文管理器、生成器
原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...
- python学习笔记4(对象/引用;多范式; 上下文管理器)
### Python的强大很大一部分原因在于,它提供有很多已经写好的,可以现成用的对象 21. 动态类型:对象/引用 对象和引用: 对象是储存在内存中的实体,对象名只是指向这一对象的引用(refere ...
- Python深入02 上下文管理器
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 上下文管理器(context manager)是Python2.5开始支持的一种语 ...
随机推荐
- IE6图片透明问题
网上很多解决IE6下png透明问题的方案,但是经本人实践,有的时候有用,有的时候并不能解决自己的问题.当是后者的时候,想到另外一种办法,就是当在IE6.IE7下使用gif图片,自己在测试的时候,如果g ...
- form-create教程:自定义布局,实现一行多个组件
本文将介绍form-create如何自定义布局,实现一行多个组件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组 ...
- TCP三次握手过程中涉及的队列知识的学习
先上一张图 (图片来源:http://www.cnxct.com/something-about-phpfpm-s-backlog/) 如上图所示,这里有两个队列:syns queue(半连接队列): ...
- GC案例
FGC----jmap -histo:live导致 线上某服务的老年代配置了CMS,但却在gc.log发现连续Full GC的问题.JVM参数配置如下: -XX:+UseCMSInitiatingOc ...
- Computer Vision_33_SIFT:Distinctive Image Features from Scale-Invariant Keypoints——2004
此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...
- Image Processing and Analysis_21_Scale Space:Scale-space theory A basic tool for analysing structures at different scales——1994
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Win7升级Win10系统提示错误0x80070057的解决方法
Win7系统用户在通过Windows Update来升级Win10系统时,有时会出现0x80070057的错误代码从而导致无法继续升级.下面好系统重装助手就来告诉大家Win7升级Win10系统出现0x ...
- 网络OSI 7层模型
OSI 的英文全程为Open Systems Interconnection ,中文全程为开放系统互联参考模型.是一个逻辑上的定义.主要用途使通信和计算系统自由互联,而不依赖其他架构或技.主要目标就是 ...
- jajx 传参 需要 判断的 条件
1.有没有权限. 2.数据类型 对不对 例如 id ,page 传过来时是str 类型, view中处理时需要转换成 int类型. 如果 不能转 就会报错.. 3.查询数据.数据不存在也要报错... ...
- jade反编译,把html编译成jade
通过上面的学习,了解了一个jade模板怎么编译成一个html页面,现在介绍一个工具,怎么把html页面编译成一个jade模板 命令行 npm install html2jade -g 安装到全局 第一 ...