深入Asyncio(八)异步迭代器
Async Iterators: async for
除了async def
和await
语法外,还有一些其它的语法,本章学习异步版的for循环与迭代器,不难理解,普通迭代器是通过__iter__
和__next__
两个特殊方法实现的,如下例。
>>> class A:
... def __iter__(self): # 1
... self.x = 0 # 2
... return self # 3
... def __next__(self): # 4
... if self.x > 2:
... raise StopIteration
... else:
... self.x += 1
... return self.x
>>> for i in A():
... print(i)
...
1
2
3
迭代器必须支持__iter__方法;
值初始化;
返回一个可迭代对象,这个对象可以执行__next__方法,这里A本身就实现了__next__方法,所以返回它本身即可;
在每次迭代时调用。
将__next__()
方法声明为异步函数,要允许await
某些IO操作,除开命名的差别外,几乎是相同的定义,PEP 492中规范说明了如何实现一个异步迭代器:
1. 实现__aiter__()
方法(不需要用async def);
2. __aiter__()
方法必须返回一个支持__anext__()
方法的对象;
3. __anext__()
必须返回迭代器的每个值,并在结束迭代时抛出StopAsyncIteration
异常。
举个例子,比如Redis的key对应的value是一个很大的集合,想迭代这些key的value会出现严重的网络IO,异步迭代器可以这样实现:
import asyncio
from aioredis import create_redis
async def main(): # 1
redis = await create_redis(('localhost', 6379)) # 2
keys = ['America', 'Africa', 'Europe', 'Asia'] # 3
async for value in OneAtTime(redis, keys): # 4
await process(value) # 5
class OneAtTime:
def __init__(self, redis, keys): # 6
self.redis = redis
self.keys = keys
def __aiter__(self): # 7
self.ikeys = iter(self.keys)
return self
async def __anext__(self): # 8
try:
k = next(self.ikeys) # 9
except StopIteration: # 10
raise StopAsyncIteration
value = await redis.get(k) # 11
return value
asyncio.get_event_loop().run_until_complete(main())
主程序入口,用于在loop.run_until_complete()方法中调用;
使用aioredis库获取异步连接;
假设每个key对应的value实例非常大;
使用async for循环,关键点是这里的迭代器可以在等待数据时切换任务;
在得到返回值后用协程去处理这个值,假设这个函数也是IO绑定的;
用一个实例来存储redis连接和keys表;
像普通迭代器一样,初始化一些值,这里我们创建一个迭代器作值,由于这个类也重载了__anext__方法,所以直接返回自身;
__anext__
方法用async def声明;迭代这个普通的迭代器;
处理普通异常并重新抛出一个异步异常;
这个调用是网络IO,因此用await切换它。
通过以上实现,将可以用一个异步for循环来迭代一些处理网络IO的异步迭代器,好处是可以只用一个事件loop就能处理大量的数据。
深入Asyncio(八)异步迭代器的更多相关文章
- 一文说通C#中的异步迭代器
今天来写写C#中的异步迭代器 - 机制.概念和一些好用的特性 迭代器的概念 迭代器的概念在C#中出现的比较早,很多人可能已经比较熟悉了. 通常迭代器会用在一些特定的场景中. 举个例子:有一个for ...
- C# 8 中的异步迭代器 IAsyncEnumerable<T> 解析
异步编程已经流行很多年了,.NET 引入的 async 和 await 关键词让异步编程更具有可读性,但有一个遗憾,在 C# 8 之前都不能使用异步的方式处理数据流,直到 C# 8 引入的 IAsyn ...
- 在Python中使用asyncio进行异步编程
对于来自JavaScript编码者来说,异步编程不是什么新东西,但对于Python开发者来说,async函数和future(类似JS的promise)可不是那么容易能理解的. Concurrency ...
- Python使用asyncio+aiohttp异步爬取猫眼电影专业版
asyncio是从pytohn3.4开始添加到标准库中的一个强大的异步并发库,可以很好地解决python中高并发的问题,入门学习可以参考官方文档 并发访问能极大的提高爬虫的性能,但是requests访 ...
- asyncio之异步上下文管理器
异步上下文管理器 前面文章我们提到了上下文管理器,但是这个上下文管理器只适用于同步代码,不能用于异步代码(async def形式),不过不用担心今天我们就来讨论在异步中如何使用上下文管理器. 特别提醒 ...
- python基础(八)-迭代器与生成器
一.迭代器 li=[1,2,3] f=li.__iter__() print(f) print(f.__next__()) print(f.__next__()) print(f.__next__() ...
- python基础(八)生成器,迭代器,装饰器,递归
生成器 在函数中使用yield关键字就会将一个普通的函数变成一个生成器(generator),普通的函数只能使用return来退出函数,而不执行return之后的代码.而生成器可以使用调用一个next ...
- Python复习笔记(八)迭代器和生成器和协程
1. 迭代器 1.1 可迭代对象 判断xxx_obj是否可以迭代 在第1步成立的前提下,调用 iter 函数得到 xxx_obj 对象的 __iter__ 方法的返回值 __iter__ 方法的返回值 ...
- JDK7新特性<八>异步io/AIO
概述 JDK7引入了Asynchronous I/O.I/O编程中,常用到两种模式:Reactor 和 Proactor.Reactor就是Java的NIO.当有事件触发时,我们得到通知,进行相应的处 ...
随机推荐
- js 数组知识复习
2.Array类型 2.1 创建数组 两种方式: 1.new Array(); //创建一个空数组 var arr1 = new Array(); //创建一个长度为10的空数组, var arr2 ...
- 自己写的页面加载进度条jquery插件
(function ($) { var progressId = "progress" + Math.round(Math.random() * 100) var progress ...
- 【Android】SQLite基本用法(转)
在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面.本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的.一. ...
- linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
1: 台式机家里面不想再走线了. 于是去某东买了个USB无线网卡.tp的WN725N USB,非常小, 和罗技的优联接收器差不多大. 2: 驱动能自己识别是不指望了,既然是usb网卡,插入USB后 ...
- Ubuntu14.04 LTS安装docker
有以下几种方式: 1. 通过系统自带包安装(可能不是最新版) $ sudo apt-get update $ sudo apt-get install -y docker.io $ sudo ln - ...
- jenkins 中 violation使用pylint
在jenkins中无法打开源码问题: 1. 在 Report Violations的 Source encoding 设置为 项目文件的编码, 如: utf-8. 缺省是 default. 2. 在 ...
- springmvc4.2.X fastjson 替换引用配置
<mvc:annotation-driven> <mvc:message-converters register-defaults="true"> < ...
- webapi 初识 net
1.新建一个webapi 项目. 2.新建筛选器文件,用户在接口执行前后进行特性操作. public class MyActionWebApiAttribute : ActionFilterAttri ...
- CSU 1997: Seating Arrangement【构造】
1997: Seating Arrangement Description Mr. Teacher老师班上一共有n个同学,编号为1到n. 在上课的时候Mr. Teacher要求同学们从左至右按1, 2 ...
- Codeforces 785D Anton and School - 2(推公式+乘法原理+组合数学)
题目链接 Anton and School - 2 对于序列中的任意一个单括号对(), 左括号左边(不含本身)有a个左括号,右括号右边(不含本身有)b个右括号. 那么答案就为 但是这样枚举左右的()的 ...