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
wisej
V2EX  ›  Python

Python 中关于 asyncio.gather()的问题

  •  
  •   wisej · 2017-11-25 00:02:34 +08:00 · 3997 次点击
    这是一个创建于 2590 天前的主题,其中的信息可能已经有所发展或是发生改变。
        loop = asyncio.get_event_loop()
        
        exerciseId = [1,2,3]
        // once 为协程
        tasks = [once(i) for i in exerciseId]
    
        loop.run_until_complete(asyncio.gather(*tasks))
    

    Expected: 执行顺序是 once(1),once(2),once(3)

    In fact: 是无序的,譬如是 2,3,1 的顺序

    于是去查看 asyncio.gather 源码的时候,发现这么一行代码:for arg in set(coros_or_futures):。这个函数对列表 tasks 先进行了一次 set()操作,而 set 在 python 里是通过 hash 实现的,所以导致的无序是么?

    那现在我希望按列表里的顺序进行添加 Task 操作,有什么好的办法呢?

    9 条回复    2017-11-25 12:49:35 +08:00
    n329291362
        1
    n329291362  
       2017-11-25 00:41:22 +08:00 via iPhone
    同步运行就有顺序了?
    NoAnyLove
        2
    NoAnyLove  
       2017-11-25 01:09:02 +08:00   ❤️ 1
    如果想要按照顺序依次添加,那就依次实例化 asyncio.Task 就行了。


    tasks = [asyncio.Task(once(i)) for i in exerciseId]

    或者依次调用 ensure_future 也行,

    tasks = [asyncio.ensure_future(once(i)) for i in exerciseId]
    wisej
        3
    wisej  
    OP
       2017-11-25 02:06:04 +08:00
    @NoAnyLove 感谢~明天试试
    wisej
        4
    wisej  
    OP
       2017-11-25 02:06:19 +08:00
    @NoAnyLove 不对。。今天
    owenliang
        5
    owenliang  
       2017-11-25 08:27:28 +08:00 via Android
    python 真是强行异步,晦涩啊
    janxin
        6
    janxin  
       2017-11-25 09:41:55 +08:00 via Android
    @owenliang 所有的异步都是增加逻辑负担的,所以最好的方式当然是同步的方式写异步
    iyaozhen
        7
    iyaozhen  
       2017-11-25 11:25:01 +08:00 via Android
    话说你用了协程这几个任务应该不需要有先后的依赖吧。
    wisej
        8
    wisej  
    OP
       2017-11-25 11:42:13 +08:00
    @iyaozhen 是的,协程之间没有先后的依赖。但是他们的完成需要两个参数,p1,p2.p1 就是问题描述中 exerciseId 列表内的元素,p2 是个常数。问题是,exerciseId 内第一个元素对应的就是 p2,之后 exerciseId 每迭代一次,p2 自增 1.
    之前写同步代码时,就是迭代列表 exerciseId,执行函数,自增 1.但是异步之后,由于函数的执行不是按列表的顺序,而是无序的,就会导致 p1 p2 对应出错。
    在 V 友给出方案之前,我只好建立个字典,提前把 p1、p2 映射关系算出来保存。

    所以就是:也可以不需要有先后依赖,但是按顺序来的话,会比较省事,不用改原来的代码
    iyaozhen
        9
    iyaozhen  
       2017-11-25 12:49:35 +08:00 via Android
    @wisej 哦哦,不过 Python 协程用起来感觉真别扭
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2806 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 07:05 · PVG 15:05 · LAX 23:05 · JFK 02:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.