Eog*_*anM 9 python asynchronous python-asyncio
自从 Python 中引入了迭代器以来,你总是可以不关心你正在处理的是迭代器还是列表:
from random import random
def gen_list():
print('gen')
for i in range(10):
yield i
def return_list():
print('return')
return [i for i in range(10)]
if random() > 0.5:
x = gen_list()
else:
x = return_list()
for i in x:
pass
Run Code Online (Sandbox Code Playgroud)
PEP 492 引入了异步迭代器和async for语法。我看不出向异步迭代器的使用者添加语法的新负担有任何理由。
在我的代码中,我有时处理列表(来自缓存),有时处理异步生成器:
import asyncio
from random import random
def is_small_and_in_cache():
if random() > 0.5:
print('in fake cache')
return [i for i in range(10)]
async def get_progressively():
print('gen')
for i in range(10):
# e.g. an await here
await asyncio.sleep(0.1)
yield i
async def main():
x = is_small_and_in_cache()
if x is None:
x = get_progressively()
async for i in x:
pass
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)
但上面的方法失败了(一半的时间)TypeError: 'async for' requires an object with __aiter__ method, got list。
主要问题:如何写这个以便我们可以处理其中任何一个?我应该尝试将列表转换为虚拟异步生成器,还是包装异步生成器以使其生成列表?
支线任务:是否有任何建议可以摆脱(对我来说显然不是Python的)async for构造,即为什么常规循环不能for处理异步生成器?Python3x 在可用性方面迷失了方向吗?
该语法的存在是为了警告您,您的 \xe2\x80\x9cloop\xe2\x80\x9d 实际上可能包括挂起您的整个调用,允许其他代码运行,以便您知道在顶部有处于一致状态的适当数据。每次迭代。它\xe2\x80\x99s不会去任何地方。
\n当然,协程不需要挂起\xe2\x80\x99 ,你可以使用它来包装任何可迭代的琐事:
\nasync def desync(it):\n for x in it: yield x\nRun Code Online (Sandbox Code Playgroud)\n这比仍然异步的相反数字更有用,因为它必须收集到一个列表中:
\nasync def gather(ai):\n ret=[]\n async for x in ai: ret.append(x)\n return ret\nRun Code Online (Sandbox Code Playgroud)\n因为它允许在完全异步的情况下进行适当的交错。
\n| 归档时间: |
|
| 查看次数: |
6296 次 |
| 最近记录: |