首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >锁在Asyncio

锁在Asyncio
EN

Stack Overflow用户
提问于 2022-11-14 22:00:08
回答 1查看 41关注 0票数 1

我试图使用Asyncio中的Lock来防止函数方法()“同时运行更多的”。

我的动机是:我使用Asyncio库与多个设备进行异步通信。问题是,设备需要一些时间来响应,如果同时向同一设备发送其他请求,则会发生错误。所以我想在(设备的)类中建一个锁以防止这种情况发生。

这段代码只是测试概念并在将其实现到实际代码之前理解它的非常简单的方法。但是,即使这个测试代码也不能像我预期的那样工作。:D

首先:如果我试图运行以下代码:

代码语言:javascript
复制
import asyncio

async def method(wait:int):
  print(f"Method with waiting {wait}s starting")
  await asyncio.sleep(wait)
  print(f"Method with waiting {wait}s finished")

async def main():
  task1 = asyncio.create_task(method(2))
  task2 = asyncio.create_task(method(2))
  await task1
  await task2

asyncio.run(main())

task1开始执行,然后休眠,因此task2启动。然后他们就这样结束了(这也是意料之中的):

代码语言:javascript
复制
Method with waiting 2s starting
Method with waiting 2s starting
Method with waiting 2s finished
Method with waiting 2s finished

现在,我希望防止在task2完成之前启动task1的执行。最好的方法(我认为)是与洛克。所以我修改了代码:

代码语言:javascript
复制
import asyncio
locker = asyncio.Lock()

async def method(wait:int):
  async with locker:
    print(f"Method with waiting {wait}s starting")
    await asyncio.sleep(wait)
    print(f"Method with waiting {wait}s finished")

async def main():
  task1 = asyncio.create_task(method(2))
  task2 = asyncio.create_task(method(2))
  await task1
  await task2

asyncio.run(main())

代码不像预期的那样工作,我得到以下错误:

代码语言:javascript
复制
Method with waiting 2s starting
Method with waiting 2s finished
Traceback (most recent call last):
  File "/Users/filip/Desktop/Python/07_Asyncio2.py", line 16, in <module>
    asyncio.run(main())
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/Users/filip/Desktop/Python/07_Asyncio2.py", line 14, in main
    await task2
  File "/Users/filip/Desktop/Python/07_Asyncio2.py", line 5, in method
    async with locker:
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/locks.py", line 14, in __aenter__
    await self.acquire()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/locks.py", line 120, in acquire
    await fut
RuntimeError: Task <Task pending name='Task-3' coro=<method() running at /Users/filip/Desktop/Python/07_Asyncio2.py:5>> got Future <Future pending> attached to a different loop

运行在MacOS上,:3.9.5谢谢您的帮助和提示:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-15 17:44:48

以下列方式更改代码,它将工作:

代码语言:javascript
复制
import asyncio


async def method(wait: int, locker: asyncio.Lock):
    async with locker:
        print(f"Method with waiting {wait}s starting")
        await asyncio.sleep(wait)
        print(f"Method with waiting {wait}s finished")


async def main():
    locker = asyncio.Lock()
    await asyncio.gather(method(2, locker), method(2, locker))

if __name__ == '__main__':
    asyncio.run(main())

  1. 提供asyncio.Lock作为函数参数
  2. 使用asyncio.gather同时运行任务,就像您使用tasks时根本不需要锁一样。

主要的问题是您的锁和您的协同器属于不同的事件循环,所以我将锁移到了另一个地方。

如何检查循环是否不同?在锁定声明后并在主函数开始时添加行print(id(asyncio.get_event_loop()))

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74438347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档