V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LudwigWS
V2EX  ›  Python

asyncio 协程并发发送网络请求,如何优先继续处理返回结果的任务,而不是开始发送新的请求?

  •  
  •   LudwigWS · 2021-04-25 10:49:37 +08:00 · 1395 次点击
    这是一个创建于 1339 天前的主题,其中的信息可能已经有所发展或是发生改变。
    import asyncio
    
    import httpx
    
    request_time = 10
    
    limits = httpx.Limits(max_connections=5)
    client = httpx.AsyncClient(limits=limits)
    
    
    async def request_baidu(i):
        # async with httpx.AsyncClient(limits=limits) as client:
            print(f"===> %d" % i)
            r = await client.get("http://www.baidu.com")
            # print(r.status_code)
            print(f"<=== %d" % i) # 如何保证优先执行此处代码,而不发送新的请求?
    
    
    async def main():
        request_list = [asyncio.create_task(request_baidu(i)) for i in range(request_time)]
        await asyncio.gather(*request_list)
    
    if __name__ == '__main__':
        asyncio.run(main())
    
    """
    ===> 0
    ===> 1
    ===> 2
    ===> 3
    ===> 4
    ===> 5
    ===> 6
    ===> 7
    ===> 8
    ===> 9
    <=== 3
    <=== 4
    <=== 0 # 可以看到发送完所有的网络请求,才开始处理返回的结果
    <=== 1
    <=== 2
    <=== 5
    <=== 6
    <=== 7
    <=== 8
    <=== 9
    
    期望的结果:
    ===> 0
    ===> 1
    <=== 0 # 在前面的请求放回结果的时候优先返回该处继续向下执行,而不是发送新的请求
    ===> 2
    ===> 3
    <=== 1
    <=== 2
    ===> 4
    ...
    """
    
    linw1995
        1
    linw1995  
       2021-04-25 12:33:20 +08:00   ❤️ 1
    主因是这个服务响应得太快。如果我没理解错你的诉求的话,你期望的没法简单的实现。你这个例子可分解成,做网络请求,再对响应内容作处理。看 asyncio loop._run_once 的源码,你可以发现 IO 事件是优先执行的。你想优先处理非 IO 事件的协程,只能串行执行了。

    那可以这样,先处理所有 响应内容,再做一次请求

    ```python
    def handle_loop(q_request, q_response):
    while True:
    await handle_response(q_response) # 执行全部
    await handle_request(q_request) # 执行一个
    ```

    以上就是本人粗略判断得出来的结论
    LudwigWS
        2
    LudwigWS  
    OP
       2021-04-25 13:09:44 +08:00
    @linw1995 感谢,我研究一下源码和考虑一下其他写法。昨天研究了一个晚上,折腾到凌晨两点都没想明白😂
    ClericPy
        3
    ClericPy  
       2021-04-25 20:54:26 +08:00
    你描述的场景... 是要把并发改串行吗, 一时间没看懂需求

    就字面意思, 能想到的就是 asyncio.Semophare, asyncio.Lock 之类的
    LudwigWS
        4
    LudwigWS  
    OP
       2021-04-25 22:27:08 +08:00
    @ClericPy 还是并发,但是要求如果有响应就处理响应的结果,现在是发送完所有的请求再返回处理响应了,等于前面的结果一直阻塞等到最后才被处理
    joApioVVx4M4X6Rf
        5
    joApioVVx4M4X6Rf  
       2021-04-28 15:52:47 +08:00
    最后你是怎么解决的?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2968 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:32 · PVG 21:32 · LAX 05:32 · JFK 08:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.