[英]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.