You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python遍历网络设备CSV时的无效凭证异常处理方法

问题:处理Palo Alto设备认证异常的脚本优化

我是Python新手,编写脚本用于遍历CSV列表中的Palo Alto防火墙设备并获取系统信息。认证成功的设备可正常输出数据,但部分设备抛出无效凭证错误,现附上代码及报错栈信息,恳请指导如何正确处理该类异常。

原代码

file_csv = open('device_csv_test.txt','r')
lines = file_csv.readlines()
file_csv.close()
lines_ = [line.strip() for line in lines[1:]] 


# create list of IPs that we need to pull uptime

device_ip_list =[]
for line in lines_:
    device_data = line.split("\t")
    device_name = device_data[0]
    device_ip = device_data[1]
    device_ip_list.append(device_ip)



# function that gets system_info details

def system_info(ip):
    urllib3.disable_warnings()
    try:
        fw = firewall.Firewall(ip, username, password)
    except ValueError:
        print(f"{device_name} is no longer accessible OR might have invalid cred")
    else: 
        system_info = fw.op ("show system info", xml=True )                  # without xml=True, it is going to return object only , but with xml=True arg, it is return a string with xml data
        system_info_json = xmltodict.parse(system_info)        
        uptime = system_info_json["response"]["result"]["system"]["uptime"]
        device_name = system_info_json["response"]["result"]["system"]["hostname"]
        dict_ = [{'device_name':device_name ,'uptime': uptime}]
        writer.writerows(dict_)
        # writer.writerows([elm.values() for elm in dict_])       # parse value of dict


# write parsed data (hostname , uptime) into CSV file
start_time = timeit.default_timer()
with open ("new_csv.csv","w") as f:
    writer = csv.DictWriter(f, fieldnames= ['device_name','uptime'])     # create header
    writer.writeheader()                                             # write header in csv
    # writer = csv.writer(f)         t
   # f.write('hostname,uptime\n')
    for ips in device_ip_list:
        system_info(ips)
end_time = timeit.default_timer()
print(f"total time = {end_time - start_time}")

报错信息

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 3878, in method
    super_method(self, *args, **kwargs)
  File "/home/admin/palo_nat/lib/python3.11/site-packages/pan/xapi.py", line 637, in keygen
    raise PanXapiError(self.status_detail)
pan.xapi.PanXapiError: URLError: code: 403 reason: Invalid Credential

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/admin/palo_uptime_test.py", line 70, in <module>
    system_info(ips)
  File "/home/admin/palo_uptime_test.py", line 53, in system_info
    system_info = fw.op ("show system info", xml=True )                  # without xml=True, it is going to return object only , but with xml=True arg, it is return a string with xml data
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/firewall.py", line 242, in op
    return super(Firewall, self).op(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 4047, in op
    element = self.xapi.op(cmd, vsys, False, extra_qs, retry_on_peer=retry_on_peer)
              ^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 4000, in xapi
    self._xapi_private = self.generate_xapi()
                         ^^^^^^^^^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/firewall.py", line 255, in generate_xapi
    return super(Firewall, self).generate_xapi()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 4072, in generate_xapi
    "api_key": self.api_key,
               ^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 3994, in api_key
    self._api_key = self._retrieve_api_key()
                    ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 4159, in _retrieve_api_key
    xapi.keygen(retry_on_peer=False)
  File "/home/admin/palo_nat/lib/python3.11/site-packages/panos/base.py", line 3897, in method
    raise the_exception
panos.errors.PanURLError: URLError: code: 403 reason: Invalid Credential

解决方案

核心问题分析

  1. 原代码仅捕获ValueError,但实际抛出的是panos.errors.PanURLError和pan.xapi.PanXapiError,导致异常未被处理。
  2. device_name变量作用域错误:函数内引用的是循环变量,循环结束后值会混乱,需将设备名和IP绑定传入函数。
  3. 文件读取未用with语句,存在资源泄漏风险。

修改后的代码

import csv
import timeit
import urllib3
import xmltodict
from panos.firewall import Firewall
from panos.errors import PanURLError, PanXapiError
from pan.xapi import PanXapiError as PanXapiErrorOriginal

# 禁用SSL警告
urllib3.disable_warnings()

# 读取设备列表,存储为(设备名, IP)的元组列表
device_list = []
with open('device_csv_test.txt', 'r') as file_csv:
    # 跳过表头
    next(file_csv)
    for line in file_csv:
        line = line.strip()
        if not line:
            continue
        device_data = line.split("\t")
        device_name = device_data[0]
        device_ip = device_data[1]
        device_list.append((device_name, device_ip))

# 获取系统信息的函数,传入设备名、IP、认证信息和写入器
def get_system_info(device_name, device_ip, username, password, writer):
    try:
        fw = Firewall(device_ip, username, password)
        # 执行命令获取系统信息
        system_info_xml = fw.op("show system info", xml=True)
        system_info_json = xmltodict.parse(system_info_xml)
        system_data = system_info_json["response"]["result"]["system"]
        uptime = system_data["uptime"]
        # 用设备返回的hostname,也可以直接用传入的device_name
        hostname = system_data["hostname"]
        writer.writerow({'device_name': hostname, 'uptime': uptime})
        print(f"成功获取 {device_name} ({device_ip}) 的信息")
    except PanURLError as e:
        if "Invalid Credential" in str(e):
            print(f"错误:{device_name} ({device_ip}) 凭证无效 - {e}")
        else:
            print(f"错误:{device_name} ({device_ip}) 连接失败 - {e}")
    except (PanXapiError, PanXapiErrorOriginal) as e:
        print(f"API错误:{device_name} ({device_ip}) - {e}")
    except Exception as e:
        print(f"未知错误:{device_name} ({device_ip}) - {e}")

# 主逻辑:写入结果到CSV
start_time = timeit.default_timer()
with open("new_csv.csv", "w", newline='') as f:
    writer = csv.DictWriter(f, fieldnames=['device_name', 'uptime'])
    writer.writeheader()
    # 替换成你的实际用户名和密码
    username = "your_username"
    password = "your_password"
    for device_name, device_ip in device_list:
        get_system_info(device_name, device_ip, username, password, writer)

end_time = timeit.default_timer()
print(f"总耗时:{end_time - start_time:.2f} 秒")

关键优化点

  • 精准捕获异常:明确捕获panos库抛出的PanURLError、PanXapiError等异常,区分凭证无效和连接失败场景。
  • 修复作用域问题:将设备名和IP绑定为元组传入函数,确保错误提示的设备信息准确。
  • 安全文件操作:用with语句处理文件读写,自动管理资源,避免泄漏。
  • 明确错误提示:针对不同异常输出对应信息,方便快速排查问题。
  • 优化代码结构:拆分函数职责,主逻辑更简洁易维护。

内容的提问来源于stack exchange,提问作者Maulik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 23:37:01