【问题标题】:How to initialise data structure once in python loop如何在python循环中初始化数据结构一次
【发布时间】:2017-04-12 04:07:15
【问题描述】:

我正在尝试从 CSV 文件构建数据结构。 CSV 文件内容如下。

‘Windows 8’,10.1.1.1,’Windows 8 Server’,’SiteA’
‘Windows 8’,10.2.2.2,’Windows 8 Server’,’SiteB’
‘Cisco Router,’172.16.1.1’,’Cisco Router 881’,’SiteA’
‘Cisco Router,’172.16.1.3’,’Cisco Router 881’,’SiteC’
‘Cisco Router,’172.16.1.4’,’Cisco Router 881’,’SiteB’

我正在尝试按设备类型对数据进行分组,然后是站点,并拥有一个常见 IP 地址列表以及描述。

我遇到的问题是我无法确保我只初始化数据结构的各个部分。

下面是我的代码。

import csv
import pprint

data = {}

pp = pprint.PrettyPrinter(indent=4)


f = open('/Users/marcos/Desktop/vulns/data.csv', 'rt')
try:
    reader = csv.reader(f)
    for row in reader:
            product = row[0]
            ip = row[1]
            description = row[2]
            site = row[3]
            try:
                data[product][site]['ipaddresses'].append(ip)
                data[product][site]['description'] = description
            except:
                data[product] = {}
                data[product][site] = {}
                data[product][site]['ipaddresses'] = []
                data[product][site]['ipaddresses'].append(ip)
                data[product][site]['description'] = description

finally:
    f.close()

pp.pprint(data)

我目前得到的是以下内容,这是因为我相信我的异常总是触发

{   '‘Cisco Router': {   '’SiteB’': {   'description': '’Cisco Router     881’',
                                    'ipaddresses': ['’172.16.1.4’']}},
    '‘Windows 8’': {   '’SiteB’': {   'description': '’Windows 8 Server’',
                                  'ipaddresses': ['10.2.2.2']}}}

【问题讨论】:

  • 处理这个问题的常用方法是使用defaultdict(dict)(来自collections)自动初始化丢失的键,或者在添加到字典(或列表,或。 ..)

标签: python list csv dictionary


【解决方案1】:

引发异常有助于显示实际错误。当我这样做时,我看到了 KeyErrors,所以我使用了这种方法:

try:
    reader = csv.reader(f)
    for row in reader:
        product = row[0]
        ip = row[1]
        description = row[2]
        site = row[3]
        try:
            if product not in data:
                data[product] = {}
            if site not in data[product]:
                data[product][site] = {}
            if 'description' not in data[product][site]:
                data[product][site]['description'] = description
            if 'ipaddresses' not in data[product][site]:
                data[product][site]['ipaddresses'] = []
            data[product][site]['ipaddresses'].append(ip)
            data[product][site]['description'] = description
        except Exception, e:
            raise

finally:
    f.close()

pp.pprint(data)

请注意,在尝试使用它们之前,我正在创建所需的任何键、列表或字典。 这给了我以下输出:

{   'Cisco Router': {   'SiteA': {   'description': 'Cisco Router 881',
                                     'ipaddresses': ['172.16.1.1']},
                        'SiteB': {   'description': 'Cisco Router 881',
                                     'ipaddresses': ['172.16.1.4']},
                        'SiteC': {   'description': 'Cisco Router 881',
                                     'ipaddresses': ['172.16.1.3']}},
    'Windows 8': {   'SiteA': {   'description': 'Windows 8 Server',
                                  'ipaddresses': ['10.1.1.1']},
                     'SiteB': {   'description': 'Windows 8 Server',
                                  'ipaddresses': ['10.2.2.2']}}}

【讨论】:

    【解决方案2】:

    这是一种使用.setdefault 方法的方法。在循环中使用时,它完全符合您的要求:如果键不存在,则初始化值,否则返回存储的值。 我个人喜欢它,但我可以看到其他人不喜欢它,因为它使嵌套查找更难阅读。这是一个品味问题:

    reader = """
    ‘Windows 8’,10.1.1.1,’Windows 8 Server’,’SiteA’
    ‘Windows 8’,10.2.2.2,’Windows 8 Server’,’SiteB’
    ‘Cisco Router,’172.16.1.1’,’Cisco Router 881’,’SiteA’
    ‘Cisco Router,’172.16.1.3’,’Cisco Router 881’,’SiteC’
    ‘Cisco Router,’172.16.1.4’,’Cisco Router 881’,’SiteB’
    """
    
    reader = [line.split(',') for line in reader.replace("'", '').strip().split('\n')]
    
    data = {}
    for row in reader:
        product, ip, description, site = row[:4]
        site_data = data.setdefault(product, {}).setdefault(site, {})
        site_data.setdefault('ipaddresses', []).append(ip)
        site_data['description'] = description
    
    import pprint
    pprint.pprint(data)
    

    打印:

    {'‘Cisco Router': {'’SiteA’': {'description': '’Cisco Router 881’',
                                   'ipaddresses': ['’172.16.1.1’']},
                       '’SiteB’': {'description': '’Cisco Router 881’',
                                   'ipaddresses': ['’172.16.1.4’']},
                       '’SiteC’': {'description': '’Cisco Router 881’',
                                   'ipaddresses': ['’172.16.1.3’']}},
     '‘Windows 8’': {'’SiteA’': {'description': '’Windows 8 Server’',
                                 'ipaddresses': ['10.1.1.1']},
                     '’SiteB’': {'description': '’Windows 8 Server’',
                                 'ipaddresses': ['10.2.2.2']}}}
    

    【讨论】:

      【解决方案3】:

      这似乎是使用 pandas 的好时机。

      import pandas as pd
      
      data_ = pd.read_csv('path-to-data.csv')
      data_.columns = ['product', 'ip', 'description', 'site']
      
      # Create a 'grouped' dataset object   
      grouped = df.groupby(['product', 'site', 'ip'])
      
      # Create a dataset with a list of unique 'description' values, 
      # grouped by columns above
         unique_desc_by_group = grouped['description'].aggregate(lambda x: tuple(x))
      
      print(unique_desc_by_group)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多