异步信号量运行时错误:任务被附加到不同的循环

2024-04-25 22:52:37 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python3.7中运行以下代码时:

import asyncio

sem = asyncio.Semaphore(2)

async def work():
    async with sem:
        print('working')
        await asyncio.sleep(1)

async def main():
    await asyncio.gather(work(), work(), work())

asyncio.run(main())

由于运行时错误而失败:

^{pr2}$

Tags: 代码importasyncioasyncmaindefwithsleep
1条回答
网友
1楼 · 发布于 2024-04-25 22:52:37

这是因为信号量构造函数在asyncio/locks.py中设置了它的_loop属性:

class Semaphore(_ContextManagerMixin):

    def __init__(self, value=1, *, loop=None):
        if value < 0:
            raise ValueError("Semaphore initial value must be >= 0")
        self._value = value
        self._waiters = collections.deque()
        if loop is not None:
            self._loop = loop
        else:
            self._loop = events.get_event_loop()

但是asyncio.run()开始了一个全新的循环——在asyncio/runners.py中,文档中也提到了:

^{pr2}$

asyncio.run()之外启动的Semaphore获取异步“default”循环,因此不能与使用asyncio.run()创建的事件循环一起使用。在

解决方案

asyncio.run()调用的代码启动Semaphore。您必须将它们传递到正确的位置,还有更多的方法可以这样做,例如,您可以使用contextvars,但我只举一个最简单的例子:

import asyncio

async def work(sem):
    async with sem:
        print('working')
        await asyncio.sleep(1)

async def main():
    sem = asyncio.Semaphore(2)
    await asyncio.gather(work(sem), work(sem), work(sem))

asyncio.run(main())

相关问题 更多 >