gpt4 book ai didi

Python 3.5 async/await 与真实代码示例

转载 作者:IT老高 更新时间:2023-10-28 22:18:50 25 4
gpt4 key购买 nike

我已经阅读了大量关于 Python 3.5 async/await 的文章和教程。我不得不说我很困惑,因为有些使用 get_event_loop() 和 run_until_complete(),有些使用 ensure_future(),有些使用 asyncio.wait(),有些使用 call_soon()。

似乎我有很多选择,但我不知道它们是否完全相同,或者在某些情况下您使用循环并且在某些情况下您使用 wait()。

但问题是所有示例都使用 asyncio.sleep() 来模拟真正的慢速操作,该操作返回一个可等待的对象。一旦我尝试将这一行换成一些真实的代码,整个事情就会失败。上面写的方法和我应该如何运行还没有准备好异步/等待的第三方库之间的区别到底是什么。我确实使用 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())

我希望你明白我的失落感和我希望并行运行的简单事情。

最佳答案

如果第三方库与 async/await 不兼容,那么显然你不能轻易使用它。有两种情况:

  1. 假设库中的函数是异步的,它会给你一个回调,例如

    def fn(..., clb):
    ...

    所以你可以这样做:

    def on_result(...):
    ...

    fn(..., on_result)

    在这种情况下,您可以像这样将这些函数包装到 asyncio 协议(protocol)中:

    from asyncio import Future

    def wrapper(...):
    future = Future()
    def my_clb(...):
    future.set_result(xyz)
    fn(..., my_clb)
    return future

    (使用 future.set_exception(exc) 处理异常)

    然后你可以简单地用 await 在一些 async 函数中调用该包装器:

    value = await wrapper(...)

    请注意,await 适用于任何 Future 对象。您不必将 wrapper 声明为 async

  2. 如果库中的函数是同步的,那么您可以在单独的线程中运行它(可能您会为此使用一些线程池)。整个代码可能如下所示:

    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())

如果您出于某种原因不能使用线程,那么使用这样的库只会使整个异步代码变得毫无意义。

但是请注意,将同步库与异步一起使用可能不是一个好主意。你不会得到太多,但你却使代码复杂了很多。

关于Python 3.5 async/await 与真实代码示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39952799/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com