深入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.当有事件触发时,我们得到通知,进行相应的处 ...
随机推荐
- Swing要点
1. 布局管理器会控制潜逃在其他组件中组件的大小和位置. 2. 当某个组件加到背景组件上面时,被加入的组件是由背景组件的布局管理器管理的. 3. 布局管理器在做决定之前会询问组件的理想大小(setSi ...
- 介绍一个牛X的样式counter
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- FTP上传文件服务器python实现
总结 使用Python的socket和socketserver模块实现ftp文件服务器.不是很难,但在粘包的问题上纠缠了不少时间.解决办法是发送文件信息之后等待一段时间. #!/usr/bin/pyt ...
- hdu 3072 有向图缩点成最小树形图计算最小权
题意,从0点出发,遍历所有点,遍历边时候要付出代价,在一个SCC中的边不要付费.求最小费用. 有向图缩点(无需建立新图,,n<=50000,建则超时),遍历边,若不在一个SCC中,用一个数组更新 ...
- hdu 2145(迪杰斯特拉)
zz's Mysterious Present Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- LeetCode OJ--Sum Root to Leaf Numbers
https://oj.leetcode.com/problems/sum-root-to-leaf-numbers/ 给一棵树,找从根到叶的路径,并把路径上的数相加,求和. 树的深度优先搜索 /** ...
- LeetCode OJ-- Edit Distance **
https://oj.leetcode.com/problems/edit-distance/ 动态规划,它的小规模问题是:当 word1 word2都比较小的时候,word1变成 word2需要的 ...
- CodeForces 702B Powers of Two【二分/lower_bound找多少个数/给出一个数组 求出ai + aj等于2的幂的数对个数】
B. Powers of Two You are given n integers a1, a2, ..., an. Find the number of pairs of indexes i, ...
- usaco-Cow Pedigrees
题意: 求出n个节点可以构成多少种高为h的二叉树.分析: 设左子树节点数x,右子树节点数为n-x-1,函数dp表示满足条件的树的个数,则dp(n)=dp(x)*(n-x-1). 对于未知数h,dp[n ...
- POJ 3480 John [博弈之Nim 与 Anti-Nim]
Nim游戏:有n堆石子,每堆个数不一,两人依次捡石子,每次只能从一堆中至少捡一个.捡走最后一个石子胜. 先手胜负:将所有堆的石子数进行异或(xor),最后值为0则先手输,否则先手胜. ======== ...