利用asyncio在列表中循环并进行调用,而无需等待上一个列表的响应

2024-10-01 00:33:48 发布

您现在位置:Python中文网/ 问答频道 /正文

async def load_devices(deviceName):
    deviceIP = deviceName[1]
    deviceNumber = deviceName[2]
    device = BAC0.device(deviceIP, deviceNumber, bacnet, poll=trends_every)
    return device  

def get_attributes(self):
    self.get_attribute_button.destroy()

    deviceNames = list(bacnet.devices.values.tolist())

    loop = asyncio.get_event_loop()

    global devices

    for device in deviceNames:
        devices = loop.run_until_complete(asyncio.gather(load_devices(device)))
    loop.close()

我已经做了很多冲浪解决这个问题,没有一个应用程序,我发现工作时,适用于我的情况。device()callout是我的代码一直在等待的。在上一个设备调用返回之前,我现在看到的不会移到下一个设备调用,这会显著降低性能。你知道吗

我需要做的是异步创建这些设备,这样就不会一直等待前一个设备连接,然后再创建下一个设备。谢谢你的建议/帮助!你知道吗


Tags: selfloopasynciogetasyncdevicedefload
2条回答

现在,您的load_devices是异步的,但是您正在等待对它的每个调用完成,然后再开始下一个调用。你知道吗

我会用这个来替换最后的for循环。你知道吗

tasks = [load_devices(device) for device in deviceNames]
await asyncio.gather(*tasks)

这使得每个呼叫都可以等待,然后一次等待所有呼叫,而不是单独等待每个呼叫。你知道吗

(注意:tasks列表技术上包含协同程序,而不是Task对象,因为asyncio.gather自动执行所有Task创建。如果您真的愿意,您可以对每一个运行asyncio.create_task,但它不会改变结果。)

编辑:听起来像是要在非异步函数中执行此操作。在这种情况下:

tasks = [load_devices(device) for device in deviceNames]
devices = loop.run_until_complete(asyncio.gather(*tasks))

值得注意的是,对BAC0.device的每个调用都依赖于bacpypes(处理BACnet通信的模块)在创建BACnet网络时创建的线程。这个线程使所有的网络调用一个接一个地执行。你知道吗

Bacpypes(因为BACnet的工作方式)将保持socket在运行期间保持打开状态,因此您将无法启动同时运行的多个BACnet实例。。。您将需要多个NIC(或任何其他允许打开新套接字的技巧)才能使其异步。你知道吗

如果你想提高速度,我想你会有更好的结果定义所有的设备全局,并使用自定义对象列表,以减少点数。你知道吗

一旦定义,所有设备都将在后台更新。然后你可以使用

dev[“MyPoint”].lastValue

强制软件使用上次轮询的值的技巧(而不是强制在网络上进行新的读取)

如果您真的想使用异步并等待BACnet通信,您可能需要从bacpypes本身开始。我知道Joel正在考虑一种使模块异步化的方法,但这还很遥远。但是BAC0不过是bacpypes的“包装器”,它实际上是“同步的”。你知道吗

如果BAC0要在一个异步应用程序中使用,我认为有一些“方法”来处理同步的东西,但是这里结束了我关于异步的知识。你知道吗

顺便说一句,如果你在这方面取得了一些进展,请不要犹豫,顺道拜访Github并留下一些东西!我很想知道BAC0的用途。你知道吗

相关问题 更多 >