【发布时间】:2017-05-12 13:51:33
【问题描述】:
我正在尝试将此 Python2.7 代码重写为新的异步世界秩序:
def get_api_results(func, iterable):
pool = multiprocessing.Pool(5)
for res in pool.map(func, iterable):
yield res
map() 阻塞,直到计算出所有结果,所以我试图将其重写为异步实现,一旦它们准备好就会产生结果。与map() 一样,返回值的返回顺序必须与iterable 相同。我试过这个(我需要requests,因为旧的身份验证要求):
import requests
def get(i):
r = requests.get('https://example.com/api/items/%s' % i)
return i, r.json()
async def get_api_results():
loop = asyncio.get_event_loop()
futures = []
for n in range(1, 11):
futures.append(loop.run_in_executor(None, get, n))
async for f in futures:
k, v = await f
yield k, v
for r in get_api_results():
print(r)
但是使用 Python 3.6 我得到了:
File "scratch.py", line 16, in <module>
for r in get_api_results():
TypeError: 'async_generator' object is not iterable
我怎样才能做到这一点?
【问题讨论】:
-
不要将事件循环放在异步代码块中,异步代码必须由事件循环运行,而不是相反。
-
谢谢!当然,我在这里遗漏了一些东西。我见过的所有事件循环示例都使用 loop.run_until_complete(get_api_results()) 在我的理解中,这会使调用阻塞并丢失结果。
-
你通常会有更多的协程来处理结果,而事件循环会驱动这些。
-
另外,
requests.get()是一个阻塞调用,不是你可以等待的。 -
是的,这就是为什么我按照stackoverflow.com/questions/22190403/… 中的建议将它包装在
loop.run_in_executor()中
标签: python asynchronous async-await generator python-asyncio