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

2017-11-25 00:02:34 +08:00
 wisej
    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 操作,有什么好的办法呢?

3891 次点击
所在节点    Python
9 条回复
n329291362
2017-11-25 00:41:22 +08:00
同步运行就有顺序了?
NoAnyLove
2017-11-25 01:09:02 +08:00
如果想要按照顺序依次添加,那就依次实例化 asyncio.Task 就行了。


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

或者依次调用 ensure_future 也行,

tasks = [asyncio.ensure_future(once(i)) for i in exerciseId]
wisej
2017-11-25 02:06:04 +08:00
@NoAnyLove 感谢~明天试试
wisej
2017-11-25 02:06:19 +08:00
@NoAnyLove 不对。。今天
owenliang
2017-11-25 08:27:28 +08:00
python 真是强行异步,晦涩啊
janxin
2017-11-25 09:41:55 +08:00
@owenliang 所有的异步都是增加逻辑负担的,所以最好的方式当然是同步的方式写异步
iyaozhen
2017-11-25 11:25:01 +08:00
话说你用了协程这几个任务应该不需要有先后的依赖吧。
wisej
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
2017-11-25 12:49:35 +08:00
@wisej 哦哦,不过 Python 协程用起来感觉真别扭

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/409371

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX