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

如何让 asyncio 按照优先级顺序来执行执行几个有优先级的可等待对象?

  •  
  •   abersheeran ·
    abersheeran · 88 天前 · 1147 次点击
    这是一个创建于 88 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设事件循环里有一百万个可等待对象,其中一万个可以继续进行了,其他的仍然在等待。那么如何让这一万对象按照优先级顺序顺序执行?

    我猜测要从 asyncio 源码下手,有没有读过源码的大佬给个大概的可入手的地方,比如事件循环是在哪里遍历对象判断可执行的?或者有现成的仓库?(谷歌、必应、百度过,没搜到,所以我猜大概率没有,就算有,也是藏得很深的)

    abersheeran
        2
    abersheeran   88 天前
    @wellsc 我想问的是优先级,而不是命名。
    ruanimal
        3
    ruanimal   88 天前
    @abersheeran 把任务放优先队列里就行了
    BBrother
        4
    BBrother   88 天前
    可不可以全局维护一个优先级表,每个 task 执行前先查询优先级,如果不是最高的,就再把自己加入到事件循环中?
    geebos
        5
    geebos   88 天前
    自定义一个 eventloop,在 task 类上添加一个优先级,在 select 的时候把准备好的任务添加到优先队列里再执行,但是感觉性能不太好。我建议分几个优先级,不同优先级有执行顺序,相同优先级的按到达顺序执行,这样在选取的时候遍历一遍就可以。
    wellsc
        6
    wellsc   88 天前 via iPhone
    @abersheeran 按照命名排序不就好了
    abersheeran
        7
    abersheeran   88 天前
    不回复以上回复,是因为我不想开口骂人。

    有没有真正 hack 过 asyncio 事件循环的大佬能给点具体的建议?
    BBCCBB
        8
    BBCCBB   88 天前
    每个对象加一个 condition?
    然后后一个对象等待前一个对象的 condition signal. 看看这样可不可行
    BBCCBB
        9
    BBCCBB   88 天前
    或者楼上说的放优先队列里一个一个拿出来跑也没问题呀.
    abersheeran
        10
    abersheeran   88 天前
    @BBCCBB 问题里我觉得我问的很明确了,我想要的是具体的入手点或者现有的库,而不是思路。优先级队列这种入门级的思路,我也能想到啊,关键是这个队列放在哪?在哪里把元素放进去?事件循环里哪个 API 可以用来 hack 这种操作?我想要的是这些。
    BBCCBB
        11
    BBCCBB   88 天前
    当我没说.

    假设事件循环里有一百万个可等待对象,其中一万个可以继续进行了,其他的仍然在等待。那么如何让这一万对象按照优先级顺序顺序执行?

    大家回答的你第一个问题.
    hgrx
        12
    hgrx   88 天前
    不想骂人可还行,在论坛发了这个帖子这个帖子就是你家了?别人不能进来谈一下看法?你只是发起了一个讨论,你没有拥有这个帖子,你也没资格指责别人怎么不如你意了
    abersheeran
        13
    abersheeran   88 天前
    @BBCCBB ……好的,下次我尽量让问题重点更显眼一些。

    @hgrx 你当然有发评论的权力,我同样有反驳你发的评论的权力,包括对你们评论的批评和猛烈批评,我只是用了一个口语化的形容——“骂”。怎么?只讲你们的权力,我就是没人权的人了?
    lyzh
        14
    lyzh   88 天前
    @hgrx 所以他没开口骂人你都觉得不爽,那我来阴阳你一下你你开心咯?
    se77en
        15
    se77en   87 天前
    asyncio.wait 有个 return_when 参数,可以参考一下这个 https://stackoverflow.com/a/48567863/2050626
    abersheeran
        16
    abersheeran   87 天前
    @se77en 谢谢,这个我也搜到了。不过它这个并没有真的实现一个按照优先级执行的事件循环。

    这个问题我打算给它沉掉,有一个看过源码的大佬说这个搞不定,没有对应的 API 。符合我最开始的推断,只能像 trio 一样重写一套,成本太高了。唉。不过还是谢谢你花时间帮我搜答案。
    linw1995
        17
    linw1995   87 天前   ❤️ 2
    1. 让各个 asyncio.Task 带上优先级
    可以通过 loop.set_task_factory 让各个 coroutines 有优先级,可以不修改 Task 对象,优先级存在 context 里就好了。这样其产生的新 task 可以继承这个优先级

    2. 修改 loop._run_once 使其按优先级执行(不行)
    _run_once 是在跑一个个 callbacks,所以没法用来使 asyncio.Task 按优先级执行

    所以就只能在 asyncio.Task.__step 这里搞幺蛾子了,维持一个全局的优先级堆,执行 __step 先检查一下自己的优先级在不在堆顶,看该不该继续执行,不该就重新 call_soon 。

    按这个思路应该可以搞起来
    abersheeran
        18
    abersheeran   87 天前
    @linw1995 这样就是在 asyncio 里,手动创建一个由 Task 作为基本单位的带优先级的事件循环。看起来可行!感谢!

    这个思路我是真没想到,不需要去走 loop 的接口,只要调整 Task,保证每个可等待对象都被 Task 包装起来就行了。太有意思了。是我之前的想法钻牛角尖了😭
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2794 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 11:23 · PVG 19:23 · LAX 03:23 · JFK 06:23
    ♥ Do have faith in what you're doing.