[英]how to remove value from list safely in asyncio
有一个全局list
来存储数据。 不同的异步函数可能会从中add
或remove
值。
例子:
a = [] # List[Connection]
async def foo():
for v in a:
await v.send('msg')
async def bar():
await SomeAsyncFunc()
a.pop(0)
foo
和bar
都会放弃控制权让其他协程运行,因此在foo
中,从列表中删除值是不安全的。
以下示例显示了如何为此使用锁:
创建连接管理器:
import asyncio
class ConnectionsManager:
def __init__(self, timeout=5):
self.timeout = timeout
self._lock = asyncio.Lock()
self._connections = []
async def __aenter__(self):
await asyncio.wait_for(self._lock.acquire(), timeout=self.timeout)
return self._connections
async def __aexit__(self, *exc):
self._lock.release()
超时是一种通过循环等待来解决错误的安全措施。
管理器可以按如下方式使用:
async def foo():
for _ in range(10):
async with cm as connections:
# do stuff with connection
await asyncio.sleep(0.25)
connections.append('foo')
async def bar():
for _ in range(5):
async with cm as connections:
# do stuff with connection
await asyncio.sleep(0.5)
if len(connections) > 1:
connections.pop()
else:
connections.append('bar')
cm = ConnectionsManager()
t1 = asyncio.create_task(foo())
t2 = asyncio.create_task(bar())
await t1
await t2
async with cm as connections:
print(connections)
请注意,您也可以在此处更明确地使用连接:
async def foo(cm):
...
async def bar(cm):
...
只是为了发表评论,为什么与全局变量相比,显式如此有益。 在某些时候,您可能需要为代码编写单元测试,您需要指定函数/方法的所有输入。 忘记函数隐式输入的条件(使用的全局变量)很容易导致未经测试的状态。 例如,您的bar
协程需要列表a
中的一个元素,如果它为空,它将中断。 大多数时候它可能会做正确的事情,但有一天在生产中......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.