【问题标题】:How to create an asyncio object in python3?如何在 python3 中创建 asyncio 对象?
【发布时间】:2021-08-06 13:01:39
【问题描述】:

很清楚我是如何在 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,不是吗?

有人可以发布一个例子吗? 非常感谢。

【问题讨论】:

    标签: python-3.x python-asyncio


    【解决方案1】:

    请看一下this answer,它使用旧的基于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 是阻塞的并且不提供回调,因此它不能直接转换为基于协程的形式。处理这种情况的常用方法是在异步线程中运行它(请参阅this answer 中的链接)。

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

    【讨论】:

    • 谢谢你的例子。是否可以使用另一个包含 url 请求的函数而不是 lambda 函数?那会很好,因为延迟可以作为超时工作。
    • @ThomasK 不,上面示例中的 lambda 仅用于标记某些未来已完成。它立即发生。常规阻塞请求只会阻塞事件循环。如果你想要异步请求 - 使用aiohttp。如果你想要异步超时 - 使用asyncio.wait_for,它有一个超时参数。
    【解决方案2】:

    您可以等待所有协程,因此任何带有前缀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 在默认情况下是阻塞的(不允许其他代码在它完成之前运行),所以将它“包装”在等待函数中并不容易。

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

    【讨论】:

    • 感谢您的快速回答。 :) “因为默认情况下 urllib 是阻塞的(不允许其他代码在它完成之前运行),所以将它“包装”在一个等待函数中并不容易。” 是的,但是这正是我想知道的,这也是我使用 urllib 添加示例的原因。这会是什么样子?
    • @ThomasK 我发现了这个,如果它仍然有效,但它似乎做了你想要的事情:gist.github.com/memee/66f85aea70f49489eb09
    • 谢谢你的链接,这就是我搜索的内容。你知道@Mikhail Gerasimov 建议的区别吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 2015-08-19
    相关资源
    最近更新 更多