首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
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
V2EX  ›  Python

异步大量请求,如何获得第一个有效的返回值?

  •  
  •   billgreen1 · 69 天前 · 1728 次点击
    这是一个创建于 69 天前的主题,其中的信息可能已经有所发展或是发生改变。
    情景:
    我的一个 list 中,有很多 future, 每个执行耗时不定。返回结果 None 或者 某个值。
    future1..futuren 中,第一个不为 None 的值,就是我想要的。
    如果用下面的语句
    ```python
    result = yield [future1(), future2(), ....]
    ```
    会把所有的都执行完。

    但是有可能会有这种情况:
    future1,future2 结果返回 None,future3 不为 None
    我就可以直接取 future3 的结果了。


    请教如何实现?
    16 回复  |  直到 2018-07-13 10:23:41 +08:00
        1
    noli   69 天前
    这种 polling 工作肯定都是库或者框架做的,然而你又没有具体说到底用哪个异步库或者框架。
        2
    creedowl   69 天前
    (换 js,用 promise
        3
    billgreen1   69 天前
    @noli 额,tornado,我是因为不想太限制
        4
    v2xe2v   69 天前
    结果入队列,然后轮训?
        5
    noli   69 天前
    @billgreen1
    http://www.tornadoweb.org/en/stable/queues.html

    4# @v2xe2v 思路是对的,实际上就是把结果入队列,取第一个。只不过这个队列不需要轮询这么费力而已。
        6
    lolizeppelin   69 天前 via Android
    包装一下 返回前 callback
        7
    janxin   69 天前
    你可以选择不用 yield,直接 add_done_callback
        8
    zhuweiyou   69 天前
    结果套同一个 func,判断第一个非 none 的做处理,其它的 abort
        9
    wb14123   69 天前
    所有 future 的结果都扔到一个 BlockingQueue 里面然后从这个里面取
        10
    bojoyzhou   69 天前 via iPhone
    @zhuweiyou 感觉这个方案最便捷
        11
    gjquoiai   69 天前
    我记得 pycon 2018 trio 的作者就讲了这个
        12
    so1n   69 天前
    不知道楼主的意思是不是这样的同时运行多个,然后获取返回的结果,如果是 None 忽略 不是就获取值并结束
    task_list = []
    done, pending = await asyncio.wait(task_list)
    for task in done:
    if task.result() != None:
    result = task.result()
    break
        13
    andyholo   69 天前
    rxPY 这种需求还是用专门库吧,比自己琢磨方便多了
        14
    billgreen1   68 天前
    @so1n 可能是我表述不清楚,其实是这样的:如果第一个返回的是 future3 且结果不为 None,那么我还得等 future1 和 future2。1..n 是有优先级顺序的。当 future i 返回,且有结果时,可以确定的是 i+1 到 n 是可以丢弃了,但是得等 future1 到 future (i-1)的结果
        15
    so1n   68 天前 via Android
    @billgreen1 所以你获取的顺序不是按执行结束时间排序而是按原来排列好的队列?如果是这样的话,简单点直接先遍历队列 put 到 asynico.queue 里面,再依次 get 出来运行,如果运行结果非 none 就不用再 get 直接退出来
        16
    pixcai   68 天前
    官方的 asyncio 已经提供你所需要的 API 了:
    asyncio.as_completed(fs, *, loop=None, timeout=None)
    Return an iterator whose values, when waited for, are Future instances.

    上面提到的 asyncio.wait 会等待所有的执行完,asyncio.as_completed 只要有一个执行完就立即返回,例如你要的效果:
    futures = [future1, future2, future3]
    for next_completed in asyncio.as_completed(futures):
    result = await next_completed
    if result is not None:
    break
    这样在取结果的时候,其它的 future 还在执行,应该就是你要的效果。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1705 人在线   最高记录 3762   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 16ms · UTC 16:19 · PVG 00:19 · LAX 09:19 · JFK 12:19
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1