Python字典数组是否适合处理一小部分快速变化的值?

2024-09-29 20:17:07 发布

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

我正在使用Python从少量非常健谈的空调设备收集网络流量。我看到两种类型的消息—一种只包含IP地址和设备名称,另一种包含IP地址和我要记录的值—风扇转速、温度等

这些设备生成消息的速度太快(每2-3秒一次),不太有用,我不想生成数百个毫无意义的数据库插入。我的想法是解析消息,如果我以前没有见过这个设备,就创建一个带有IP和名称的数据结构。。如果我以前见过它,我想用缺失的值更新数据结构。每隔一分钟左右,我想迭代一次数据结构,用当前值更新一个数据库。你知道吗

我认为一个对象数组可能是正确的方法,但是找不到简单的例子;对于一个设备的每个实例,字典看起来都是一个合理的结构,但是我应该把它们分组在一个数组中吗?你知道吗

抱歉,如果这是简单的-我已经多年没有编码,并享受找出如何捕捉网络流量和解析它使用正则表达式匹配。。。但是python中的大量数据结构让人无法承受! 什么是一个简单的数据结构,可以让我很容易地查询“这个设备存在吗”,或者创建一个新的,或者更新现有的?你知道吗


Tags: 对象方法ip名称数据库消息数据结构类型
3条回答

Python字典可以通过元组进行键控,因此您可以将ipname组件作为元组,并使用元组键控到存储有关设备的更多信息的字典中。

可以编写设备类:

class Device(object):        
    def __init__(self, name, ip='0.0.0.0', fanspeed=0, temp=0.0):
        self.name= name
        self.ip = ip
        self.fanspeed=fanspeed
        self.temp=temp

然后您可以拥有一个由ip键控的字典:

devices = {}

现在,每当您从设备获得新消息时,只需在字典中创建默认对象:

devices['some_ip'] = Device('some_name')

当需要用属性更新设备时,可以在字典中找到它并向对象添加一些值。你知道吗

device = devices.get('some_ip')
if device is not None:
    # set properties of device here

至于将它们写入数据库,只需像这样迭代字典:

for device in devices.values():
    # Update database with device info

^{}的这种用法来自this answer,当您试图访问丢失的键时,它会生成一个字典,为丢失的键创建相同类型的字典(正常的dict会引发KeyError)。我假设您可能会看到来自同一IP的多个设备,但没有一个设备会显示多个IP;如果不是后者,这将无法完全按照预期工作。你知道吗

from pprint import pprint
from collections import defaultdict


NestedDict = lambda: defaultdict(NestedDict)


# Catch and parse messages; contrived example
messages = (
    {"ip": "1.2.3.4", "device": "BlackBerry", "values": {"temp": 99}},
    {"ip": "1.2.3.4", "device": "Android", "values": {"fan_speed": 2}},
    {"ip": "1.2.3.4", "device": "BlackBerry", "values": {"temp": 80, "fan_speed": 2}},
    {"ip": "9.2.3.9", "device": "MacBook"},
    {"ip": "9.2.3.9", "device": "Buick", "values": {"tire_pressure": 35}},
)

devices_by_ip = NestedDict()

for message in messages:
    devices_by_ip[message["ip"]][message["device"]].update(message.get("values", {}))

pprint(devices_by_ip)

编辑为添加:如果包含值的消息没有包含设备名称,则有点不同,我们必须假设每个IP只有一个设备(即,这些消息都不是来自单独网络中的不同设备)。你知道吗

messages = (
    {"ip": "1.2.3.4", "device": "BlackBerry"},
    {"ip": "1.2.3.4", "values": {"temp": 99}},
    {"ip": "2.2.3.4", "values": {"fan_speed": 2}},
    {"ip": "2.2.3.4", "device": "Android"},
    {"ip": "1.2.3.4", "values": {"temp": 80, "fan_speed": 2}},
)

devices_by_ip = NestedDict()

for message in messages:
    if "device" in message:
        devices_by_ip[message["ip"]]["device"] = message["device"]
    else:
        devices_by_ip[message["ip"]].update(message.get("values", {}))

pprint(devices_by_ip)

我会存储一个字典,其中IPs(或者IP+设备名,如果只是IP不是唯一的)作为键,其他细节(风扇速度、温度)作为另一个字典的值。这将为您提供基于IP的固定时间查找,这在这里很重要,因为您将经常执行许多查找和更新。数据结构如下所示:

device_messages = {
  '192.168.4.3': {'device name': 'Cisco FW', 'fanspeed': 5, temperature: 56},
  '192.168.6.1': {'device name': 'NSX', 'fanspeed': 10, temperature: 90},
  '192.168.1.9': {'device name': 'Windows XP', 'fanspeed': 18, temperature: 600}
}

因此,如果有新设备进入,您可以使用以下工具执行查找:

if new_device_ip in device_messages: # this is faster than searching a list
    # update with missing information
    device_messages[new_device_ip]['fan_speed'] = new_fan_speed
    # and so on
else:
    device_messages[new_device_ip] = {}

使用对象列表然后搜索具有特定IP的条目的效率要低得多(O(n),而不是使用字典得到的O(1))。你知道吗

相关问题 更多 >

    热门问题