python - 在打印相应值时跳过特定迭代的重复值 - 我的最终目标是将其写入 CSV 文件

标签 python python-3.x set

我尝试在代码中使用 set() 来跳过迭代中的重复值;这种类型的问题可能已经在 SO 上得到了回答,但是当我尝试在脚本中执行此操作时,我没有得到所需的输出。

我正在使用 device['name'] 提取设备名称,并且 API 中的 IP 地址给出为:这是此类设备的 IP 地址的 API 响应正文:

"DTO": [
  {
    "id": "3485893021",
    "name": "Alternate Addresses",
    "IPAddress": [
      "10.228.143.125",
      "10.228.143.253",
      "10.229.184.125",
      "10.229.184.134",
      "192.21.247.125",
      "192.21.247.188",
      "192.21.247.226",
      "192.21.247.254",
      "192.21.247.61",
      "192.21.247.92",
      "192.168.53.38",
      "192.128.167.74"
     ]

像上面一样,我对单个设备有多个 IP,但是当我尝试此操作时,所有迭代的设备名称均为“无”,并且仅打印各个设备的第一个 IP。我想要的是打印所有的IP并且只打印一次它们对应的设备名称。我正在从 API 中提取这些数据。

seen = set()
seen_add = seen.add
for device in data:
    fqdn = device['name']
    for ips in device["DTO"][0]["IPaddress"]:
        if fqdn not in seen:
            print(ips, seen_add(fqdn))

这是输出:

10.228.143.125 None
10.23.54.6.8 None
10.23.6.1 None
10.22.16.34 None
10.122.25.189 None

我期待在 python 控制台输出中出现这个:

10.228.143.125 10.228.143.253 10.229.184.125 10.229.184.134 192.21.247.125 192.21.247.188 192.21.247.226 192.21.247.254 192.21.247.61 192.21.247.92 192.168.53.38 192.128.167.74 devicename1

其他此类设备依此类推...

更新:这个打印完全符合我想要的方式,但现在当我尝试将其打印在 CSV 文件上时,fqdn 和 ipaddresses 开始崩溃。谁能帮助我如何以更简单的方式写这个?

for device in data:
    fqdn = device['name']
    if fqdn not in entries:
        entries.add(fqdn)
        print("\nDevice: %s" % fqdn)
    for ips in device["DTO"][0]["IPaddress"]:
                try:
                    ipaddress.ip_address(ips)
                    print(ips)
                except ValueError:
                    print("Not Found")

Python 控制台上的输出:

Device: Device1
Not Found

Device: Device2
Not Found

Device: Device3
10.228.143.125
10.228.143.253
10.229.184.125
10.229.184.134
192.21.247.125
192.21.247.188
192.21.247.226

我尝试过在 csv 文件上打印:

with open("BNA API.csv", 'w', newline='') as f:
    fieldname = ['BNA Name', 'IP Addresses']
    writer = csv.DictWriter(f, fieldnames=fieldname)
    writer.writeheader()

for device in data:
    fqdn = device['name']
    if fqdn not in entries:
        entries.add(fqdn)
        print("\nDevice: %s" % fqdn)
    for ips in device["dynamicFields"][0]["values"]:
        try:
            ipaddress.ip_address(ips)
            print(ips)
        except ValueError:
            print("Not Found")
        with open("BNA API.csv", 'a', newline='') as f:
            writer = csv.writer(f)
            writer.writerow([fqdn, ips])

这给了我输出:

BNA Name,IP Addresses
device1,Not Found
device2,Not Found
device3,10.228.143.125
device3,10.228.143.253
device3,10.229.184.125
device3,10.229.184.134
device3,192.21.247.125
device3,192.21.247.188
device3,192.21.247.226

在我的 CSV 上,我期待这样的输出:

BNA Name,IP Addresses
device1,10.228.143.125 10.228.143.253 10.229.184.125 10.229.184.134 192.21.247.125 192.21.247.188 192.21.247.226 192.21.247.254 192.21.247.61 192.21.247.92 192.168.53.38 192.128.167.74
device2,their ip addresses and so on..

IP 地址应位于第二列,并用一个空格分隔。 这是我的 JSON 结构:

[
  {
    "name": "device1",
    "vendorName": "Cisco"
    "DTO": [
      {
        "id": "426945997-254",
        "name": "Category",
        "IPaddress": [
          "10.228.143.125",
          "10.228.143.253",
          "10.229.184.125",
          "10.229.184.134",
          "192.21.247.125"
         ],
       }
     ]
   }
 ]

这是一个此类设备的结构,我希望这是正确的,因为我无法放入所有参数,只能放入执行此代码所需的参数。 谢谢!

最佳答案

使用此数据集来测试代码:

data = [
  {
    "name": "device1",
    "vendorName": "Cisco",
    "DTO": [
      {
        "id": "426945997-254",
        "name": "Category",
        "IPaddress": [
          "10.228.143.125",
          "10.228.143.253",
          "10.229.184.125",
          "10.229.184.134",
          "192.21.247.125"
         ],
       }
     ]
   },
   {
    "name": "device2",
    "vendorName": "Cisco",
    "DTO": [
      {
        "id": "426945997-254",
        "name": "Category",
        "IPaddress": [

         ],
       }
     ]
   },
   {
    "name": "device3",
    "vendorName": "Cisco",
    "DTO": [
      {
        "id": "426945997-254",
        "name": "Category",

       }
     ]
   }
 ]

我不确定你到底在做什么,因为你的代码与键名称不匹配,但这应该适合你

import csv 
with open("BNA API.csv", 'w', newline='') as f:
    fieldname = ['BNA Name', 'IP Addresses']
    writer = csv.DictWriter(f, fieldnames=fieldname)
    writer.writeheader()

with open("BNA API.csv", 'a', newline='') as f:
    for device in data:
        fqdn = device['name']   
        try:
            ips = ' '.join(set(device["DTO"][0]["IPaddress"])) or "not found"
        except KeyError:
            ips = "not found"

        writer = csv.writer(f)
        writer.writerow([fqdn, ips])

ips = ' '.join(set(device["DTO"][0]["IPaddress"])) 或 "not find" 正在检查 IPaddress 是否为空列表Python 的 True-y 检测意味着如果集合返回空,它将采用“未找到” 代替

编辑: 似乎这个问题还有更多内容,如果您的 IP 地址错误或其他什么情况,您可以在 ' '.join() 中使用过滤器,如下所示:

bad_list = ['Firewall','Load something']
#...
#same code

try:
    ips = ' '.join(x for x in set(device["DTO"][0]["IPaddress"]) if x not in bad_list) or "not found"

if x not in bad_list 在将其添加到 .join() 之前进行检查,您可以在迭代列表时将其视为过滤器。如果您不想输入要排除的所有内容,可以将其更改为 if ipaddress(x) 并编写一个名为 ipaddress(x) 的函数,如果是则返回 True有效的 IP 地址,如果不是,则返回 false。

关于python - 在打印相应值时跳过特定迭代的重复值 - 我的最终目标是将其写入 CSV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52303720/

相关文章:

python - 在 linux mint 上制作安装脚本

Django模型-有没有办法像wagtail面板中的复选框一样选择多个页面?

java 。如何使用 forEach 检查元素是否已成功添加到集合和跟踪索引中?

java - 以下关于边界匹配器正则表达式的代码片段存在问题 (\b)

c++ - 在 C++ 中使用比较器初始化集合

python - nrfutil - Nixos 上的 "ImportError: No module named main"

python - 如何从脚本/模块 __main__ 启动 Celery worker?

Python Pandas : Delete duplicate rows based on one column and concatenate information from multiple columns

python - 在 python3 中使用 selenium 无法在页面中找到元素

python-3.x - 如何在 python3 中通过 http 传输二进制文件?