有一种方法可以async for
在Python 3.4代码中转换Python 3.5 语句吗?
PEP 0492说async for
async for TARGET in ITER: BLOCK else: BLOCK2
相当于
iter = (ITER) iter = type(iter).__aiter__(iter) running = True while running: try: TARGET = await type(iter).__anext__(iter) except StopAsyncIteration: running = False else: BLOCK else: BLOCK2
但__aiter__
在Python 3.4中不存在
不,在python 3.5中没有引入async/await
(__aiter__
等等).在py3.4上,最接近的是asyncio.gather(如果你可以同时/并行地运行所有任务并等到它们全部完成)或者将结果推送到asyncio.Queue(这是顺序的,就像async for
).编辑:请参阅最后一个示例以获取async for
替代方案,如问题中所述.
以下是asyncio.gather的ala python文档示例:
import asyncio @asyncio.coroutine def task(id): print("task: {}".format(id)) yield from asyncio.sleep(random.uniform(1, 3)) return id tasks = [ task("A"), task("B"), task("C") ] loop = asyncio.get_event_loop() results = loop.run_until_complete(asyncio.gather(*tasks)) loop.close() print(results)
输出:
task: B task: A task: C ['A', 'B', 'C']
这是asyncio.Queue的一个:
import asyncio @asyncio.coroutine def produce(queue, n): for x in range(n): print('producing {}/{}'.format(x, n)) # todo: do something more useful than sleeping :) yield from asyncio.sleep(random.random()) yield from queue.put(str(x)) @asyncio.coroutine def consume(queue): while True: item = yield from queue.get() print('consuming {}...'.format(item)) # todo: do something more useful than sleeping :) yield from asyncio.sleep(random.random()) queue.task_done() @asyncio.coroutine def run(n): queue = asyncio.Queue() # schedule the consumer consumer = asyncio.ensure_future(consume(queue)) # run the producer and wait for completion yield from produce(queue, n) # wait until the consumer has processed all items yield from queue.join() # the consumer is still awaiting for an item, cancel it consumer.cancel() loop = asyncio.get_event_loop() loop.run_until_complete(run(10)) loop.close()
编辑:async for
问题中描述的替代方案:
import asyncio import random class StopAsyncIteration(Exception): """""" class MyCounter: def __init__(self, count): self.count = count def __aiter__(self): return self @asyncio.coroutine def __anext__(self): if not self.count: raise StopAsyncIteration return (yield from self.do_something()) @asyncio.coroutine def do_something(self): yield from asyncio.sleep(random.uniform(0, 1)) self.count -= 1 return self.count @asyncio.coroutine def getNumbers(): i = MyCounter(10).__aiter__() while True: try: row = yield from i.__anext__() except StopAsyncIteration: break else: print(row) loop = asyncio.get_event_loop() loop.run_until_complete(getNumbers()) loop.close()
请注意,这可以通过删除既可以简化__aiter__
并__anext__
,提高内停止除外do_something
完成时(如通常是无效的值:方法本身或返回一个定点结果None
,""
,-1
,等)