我试图使用Asyncio中的Lock来防止函数方法()“同时运行更多的”。
我的动机是:我使用Asyncio库与多个设备进行异步通信。问题是,设备需要一些时间来响应,如果同时向同一设备发送其他请求,则会发生错误。所以我想在(设备的)类中建一个锁以防止这种情况发生。
这段代码只是测试概念并在将其实现到实际代码之前理解它的非常简单的方法。但是,即使这个测试代码也不能像我预期的那样工作。:D
首先:如果我试图运行以下代码:
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启动。然后他们就这样结束了(这也是意料之中的):
Method with waiting 2s starting
Method with waiting 2s starting
Method with waiting 2s finished
Method with waiting 2s finished现在,我希望防止在task2完成之前启动task1的执行。最好的方法(我认为)是与洛克。所以我修改了代码:
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())代码不像预期的那样工作,我得到以下错误:
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谢谢您的帮助和提示:)
发布于 2022-11-15 17:44:48
以下列方式更改代码,它将工作:
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())asyncio.Lock作为函数参数asyncio.gather同时运行任务,就像您使用tasks时根本不需要锁一样。主要的问题是您的锁和您的协同器属于不同的事件循环,所以我将锁移到了另一个地方。
如何检查循环是否不同?在锁定声明后并在主函数开始时添加行print(id(asyncio.get_event_loop()))。
https://stackoverflow.com/questions/74438347
复制相似问题