Python asyncio,可以运行一个二级事件循环吗?

aij0ehis  于 2023-02-07  发布在  Python
关注(0)|答案(1)|浏览(107)

有没有一种方法可以创建一个次要的异步循环(或优先化一个等待),当等待时不将控制传递回主事件循环,而是等待那些“子”函数?

import asyncio
async def priority1():
    print("p1 before sleep")
    await asyncio.sleep(11)
    print("p1 after sleep")

async def priority2():
    print("p2 before sleep")
    await asyncio.sleep(11)
    print("p2 after sleep")

async def foo():
    while True:
        print("foo before sleep")
        #do not pass control back to main event loop here but run these 2 async 
        await asyncio.gather(priority1(),priority2())
        print("foo after sleep")

async def bar():
    while True:
        print("bar before sleep")
        await asyncio.sleep(5)
        print("bar after sleep")

async def main():
    await asyncio.gather(foo(),bar())

asyncio.run(main())

我希望foo等待priority 1/2完成,然后再将控制权传递回主事件循环。
现在它会这样说:

foo before sleep
bar before sleep
p1 before sleep
p2 before sleep
bar after sleep

我希望看到:

foo before sleep
bar before sleep
p1 before sleep
p2 before sleep
p1 after sleep
p2 after sleep
bar after sleep

这可能吗?谢谢

jdgnovmf

jdgnovmf1#

在同一个线程上运行两个事件循环是不可能的。asyncio和specs中的代码甚至看起来像是以允许这种情况的方式来考虑的--但后来API以一种不再可能的方式弯曲了(例如,几个相关调用的显式loop参数已经被弃用和删除)
在同一行中,没有办法对运行循环中的任务子集进行优先级排序,我在几周前回答了这一行中的一个问题,并设法获得了一个同步原语,用于代替可以考虑优先级的asyncio.sleep--但它需要所有参与任务调用它,所以它不会有太大的不同锁或东西(我会链接到它下面-的想法是:您的代码在某些点调用await custom.sleep():它只会在没有其他优先级更高任务也在调用customer时返回。sleep())-在此处检查:尽快执行异步任务
在写这段代码的时候,我意识到 * 有可能 * 写一个事件循环来考虑任务的“优先级”属性,但是要做到这一点需要一些非业余爱好的工作:通过使用该循环,您可以得到您所请求的内容,而无需更改任务代码。
但是,我认为在另一个线程中运行辅助循环,然后同步等待该线程完成是完成任务的一种方法。

import asyncio
import threading

def priority(func):
    async def wrapper(*args, **kwargs):
        result = None
        def runner(*args, **kw):
            nonlocal result
            result = asyncio.run(func(*args, **kw))
        t = threading.Thread(target=runner, args=args, kwargs=kwargs)
        await asyncio.sleep(0)
        t.start()
        # if one wants to perform limited yields to the main loop, it should be done here
        t.join()
        return result

    return wrapper

async def priority1():
    print("p1 before sleep")
    await asyncio.sleep(.11)
    print("p1 after sleep")

async def priority2():
    print("p2 before sleep")
    await asyncio.sleep(.11)
    print("p2 after sleep")

@priority
async def foo():

    print("foo before sleep")
    #do not pass control back to main event loop here but run these 2 async
    await asyncio.gather(priority1(),priority2())
    print("foo after sleep")

async def bar():
    print("bar before sleep")
    await asyncio.sleep(.05)
    print("bar after sleep")

async def main():
    await asyncio.gather(foo(),bar())

asyncio.run(main())

相关问题