什么时候需要asyncio.Lock()?

问题描述 投票:0回答:1

这是我迄今为止使用 bleak 包连接到多个蓝牙设备并从中获取数据/通知的代码。这些设备是秤,如果上面没有重物,它们会在一段时间后自动关闭。一旦对它们施加重量,它们就会打开并开始发出通知。该代码不断扫描正在运行的设备,以记录其中的数据。关闭时,将调用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())

有人可以建议在这种情况下是否需要锁吗? 谢谢

python asynchronous async-await python-asyncio coroutine
1个回答
0
投票

来自文档 BleakClient 类

disconnected_callback – 将在事件中安排的回调 当客户端断开连接时循环。

asyncio 保证在等待的调用之间不会运行使用相同事件循环的其他协程。所以你不用担心你的设置操作会被中断而没有理由加锁。

如果这个集合在事件循环之外被改变,那是一个不同的故事。但除非使用该集合的所有内容都使用相同的锁,否则锁仍然没有用。

这段代码的危险之处在于,它假设暗淡回调和被跟踪的地址之间始终存在一对一的关系。您确实应该将

connected_devices.remove(client.address)
包装在异常处理程序中,以防万一。

© www.soinside.com 2019 - 2024. All rights reserved.