如何在 python3 中创建异步对象?

How to create an asyncio object in python3?

很清楚我是如何在 python3 中使用 asyncio 的。

import asyncio
import time

async def do_something(number):
    print(f"do something no.{number} at timestamp      : {time.perf_counter():6.2f}")
    await asyncio.sleep(1)
    print(f"do something no.{number} ended at timestamp: {time.perf_counter():6.2f}")

async def main():
    await asyncio.gather(
        do_something(1),
        do_something(2)
    ) 

asyncio.run(main() )

但是,我不知道如何创建自己的“await”对象,如 asyncio.sleep。在这个“await”中,我可以封装 urllib.request,不是吗?

谁能post举个例子? 非常感谢。

您可以等待所有协程,因此任何带有前缀 async 的函数都是可等待的

例如:

import asyncio


async def some_function():
    await asyncio.sleep(1)
    print("Hello")


async def main():
    await some_function()


asyncio.run(main())

您可以在 python 文档中找到有关协程的更多信息: https://docs.python.org/3/library/asyncio-task.html

因为 urllib 默认情况下是阻塞的(不允许其他代码 运行 在它完成之前),所以将它“包装”在一个可等待的函数中并不那么容易。

可能可以将其卸载到另一个线程之类的东西,然后等待该线程完成,但使用异步 Web 请求库可能更容易 aiohttp.

请看一下 它使用旧的基于 yield for 的语法,但思想保持不变:使用 asyncio.Futureloop.call_later() 你可以投射基于回调的代码转换为基于协程的代码:

import asyncio


async def my_sleep(delay):
    fut = asyncio.Future()

    loop = asyncio.get_event_loop()
    loop.call_later(
        delay,
        lambda *_: fut.set_result(True)
    )

    return await fut


async def main():
    await asyncio.gather(
        my_sleep(1),
        my_sleep(2),
        my_sleep(3)
    )
    print('ok')


asyncio.run(main())

我相信,urllib.request 是阻塞的并且不提供回调,所以它不能直接转换为基于协程的形式。处理这种情况的一种常见方法是在异步线程中 运行 它(参见 中的链接)。

但是,如果您只想进行异步 http 请求,请忘记以上所有内容并使用 aiohttp:它是为此目的而创建的。