提问人:dataengineer22 提问时间:10/28/2023 更新时间:10/28/2023 访问量:41
什么时候是 asyncio.需要 Lock() 吗?
When is asyncio.Lock() needed?
问:
这是我到目前为止拥有的代码,它使用黯淡的软件包连接到多个蓝牙设备并从中获取数据/通知。这些设备是秤,如果上面没有重物,它们会在一段时间后自动关闭。在给它们施加重量后,它们会打开并开始通知。该代码会持续扫描已打开的设备,以记录其中的数据。关闭后,将调用 disconnect_callback() 函数。
我有一个名为 connected_devices 的全局集,用于跟踪打开的设备。连接设备后,其 MAC 地址将被添加到设置中。当设备断开连接时,其 Mac 地址将从设置中删除(在 disconnect_callback() 函数中)。
我有锁定代码,这些代码目前已被注释掉,以便同步从connected_device集中添加/删除MAC地址,但我不确定是否有必要,因为一切都在scan_and_connect()协程中运行。
import asyncio
import functools
from bleak import BleakClient, BleakScanner
#lock = asyncio.Lock()
connected_devices = set()
notify_uuid = "00002A37-0000-1000-8000-00805F9B34FB"
def callback(client, characteristic, data):
print(client.address, characteristic, data)
def disconnected_callback(client):
#with lock:
connected_devices.remove(client.address)
print("disconnect from", device.address)
def match_device(device, adv_data):
#with lock:
return adv_data.local_name.startswith('BLE') and device.address not in connected_devices
async def scan_and_connect():
while True:
device = await BleakScanner.find_device_by_filter(match_device)
if device is None:
continue
client = BleakClient(device, disconnected_callback=disconnected_callback)
try:
await client.connect()
print("connected to", device.address)
await client.start_notify(functools.partial(callback, client))
#with lock:
connected_devices.add(device.address)
except BleakError:
# if failed to connect, this is a no-op, if failed to start notifications, it will disconnect
await client.disconnect()
if __name__ == "__main__":
asyncio.run(scan_and_connect())
有人可以建议在这种情况下是否需要锁吗? 谢谢
答:
从文档 BleakClient 类
disconnected_callback – 将在事件中安排的回调 在客户端断开连接时循环。
Asyncio 保证在等待的调用之间不会运行使用相同事件循环的其他协程。因此,您不必担心您的设置操作会中断,也没有理由锁定。
如果这个集合在事件循环之外被改变,那就是另一回事了。但是,除非使用该集合的所有东西都使用相同的锁,否则锁仍然没有用。
这段代码的风险在于,它假设在暗淡的回调和被跟踪的地址之间始终存在一对一的关系。为了以防万一,您确实应该包装一个异常处理程序。connected_devices.remove(client.address)
asyncio.Lock
当您需要在另一个协程可以执行并更改该状态的调用中保持稳定状态时,需要。await
评论
client.address
remove
await client.start_notify
评论