[英]Python 3.5 async/await with real code example
I've read tons of articles and tutorial about Python's 3.5 async/await thing.我已经阅读了大量关于 Python 3.5 async/await 的文章和教程。 I have to say I'm pretty confused, because some use get_event_loop() and run_until_complete(), some use ensure_future(), some use asyncio.wait(), and some use call_soon().
我不得不说我很困惑,因为有些使用 get_event_loop() 和 run_until_complete(),有些使用 ensure_future(),有些使用 asyncio.wait(),有些使用 call_soon()。
It seems like I have a lot choices, but I have no idea if they are completely identical or there are cases where you use loops and there are cases where you use wait().看起来我有很多选择,但我不知道它们是否完全相同,或者在某些情况下您使用循环并且有些情况下您使用 wait()。
But the thing is all examples work with asyncio.sleep()
as simulation of real slow operation which returns an awaitable object.但事情是所有的例子都使用
asyncio.sleep()
作为模拟真正的慢操作,它返回一个可等待的对象。 Once I try to swap this line for some real code the whole thing fails.一旦我尝试将这一行换成一些真实的代码,整个事情就会失败。 What the heck are the differences between approaches written above and how should I run a third-party library which is not ready for async/await.
上面写的方法之间到底有什么区别,我应该如何运行尚未准备好进行 async/await 的第三方库。 I do use the Quandl service to fetch some stock data.
我确实使用 Quandl 服务来获取一些股票数据。
import asyncio
import quandl
async def slow_operation(n):
# await asyncio.sleep(1) # Works because it's await ready.
await quandl.Dataset(n) # Doesn't work because it's not await ready.
async def main():
await asyncio.wait([
slow_operation("SIX/US9884981013EUR4"),
slow_operation("SIX/US88160R1014EUR4"),
])
# You don't have to use any code for 50 requests/day.
quandl.ApiConfig.api_key = "MY_SECRET_CODE"
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I hope you get the point how lost I feel and how simple thing I would like to have running in parallel.我希望你明白我是多么的失落,以及我想要并行运行的事情是多么简单。
If a third-party library is not compatible with async/await
then obviously you can't use it easily.如果第三方库与
async/await
不兼容,那么显然你不能轻易使用它。 There are two cases:有两种情况:
Let's say that the function in the library is asynchronous and it gives you a callback, eg假设库中的函数是异步的,它会给你一个回调,例如
def fn(..., clb): ...
So you can do:所以你可以这样做:
def on_result(...): ... fn(..., on_result)
In that case you can wrap such functions into the asyncio protocol like this:在这种情况下,您可以将这些函数包装到 asyncio 协议中,如下所示:
from asyncio import Future def wrapper(...): future = Future() def my_clb(...): future.set_result(xyz) fn(..., my_clb) return future
(use future.set_exception(exc)
on exception) (在异常上使用
future.set_exception(exc)
)
Then you can simply call that wrapper in some async
function with await
:然后,您可以使用
await
在某个async
函数中简单地调用该包装器:
value = await wrapper(...)
Note that await
works with any Future
object.请注意,
await
适用于任何Future
对象。 You don't have to declare wrapper
as async
.您不必将
wrapper
声明为async
。
If the function in the library is synchronous then you can run it in a separate thread (probably you would use some thread pool for that).如果库中的函数是同步的,那么您可以在单独的线程中运行它(可能您会为此使用一些线程池)。 The whole code may look like this:
整个代码可能如下所示:
import asyncio import time from concurrent.futures import ThreadPoolExecutor # Initialize 10 threads THREAD_POOL = ThreadPoolExecutor(10) def synchronous_handler(param1, ...): # Do something synchronous time.sleep(2) return "foo" # Somewhere else async def main(): loop = asyncio.get_event_loop() futures = [ loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...), ] await asyncio.wait(futures) for future in futures: print(future.result()) with THREAD_POOL: loop = asyncio.get_event_loop() loop.run_until_complete(main())
If you can't use threads for whatever reason then using such a library simply makes entire asynchronous code pointless.如果您出于某种原因不能使用线程,那么使用这样的库只会使整个异步代码变得毫无意义。
Note however that using synchronous library with async is probably a bad idea.但是请注意,将同步库与异步一起使用可能是一个坏主意。 You won't get much and yet you complicate the code a lot.
你不会得到太多,但你使代码复杂化了很多。
You can take a look at the following simple working example from here .您可以从此处查看以下简单的工作示例。 By the way it returns a string worth reading :-)
顺便说一句,它返回一个值得一读的字符串:-)
import aiohttp
import asyncio
async def fetch(client):
async with client.get('https://docs.aiohttp.org/en/stable/client_reference.html') as resp:
assert resp.status == 200
return await resp.text()
async def main():
async with aiohttp.ClientSession() as client:
html = await fetch(client)
print(html)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.