Pandas中的数据跳到其他单元格

0 投票
1 回答
72 浏览
提问于 2025-04-14 15:21

我正在尝试从网络交换机获取show interface status的信息,并把这些数据放到Pandas中(我未来还有其他计划使用这些数据)。

当我登录到网络交换机并自己运行命令时,得到了如下输出:

enter image description here 下面是交换机输出的表格版本。

端口 名称 状态 Vlan 双工 速度 类型
Fa0/1 PC DATA 已连接 1 全双工 100Mbps 10/100BaseTX
Fa0/2 PC DATA 未连接 1 自动 自动 10/100BaseTX
Fa0/3 禁用 1 自动 自动 10/100BaseTX
Fa0/4 已连接 1 全双工 100Mbps 10/100BaseTX
Fa0/5 KRONOS 未连接 1 自动 自动 10/100BaseTX
Fa0/6 KRONOS 未连接 1 自动 自动 10/100BaseTX

但是,当我在Python中使用netmiko命令并把输出作为Pandas Dataframe时,我遇到了两个问题。输出本身是正常的,但看起来像是格式或表格的问题。

  1. 如果某一行的名称单元格是空的,其他单元格会向左移动。(例如:Fa0/3和Fa0/4)
  2. 如果名称单元格中有两个或更多单词并且有空格,每个单词会填充到单元格的右侧,这样会导致数据无法使用。(例如:Fa0/1和Fa0/2)

enter image description here

这是我从代码中得到的输出.. 我也把它放成表格形式,下面可以看到两个表格之间有一些不一致。

端口 名称 状态 Vlan 双工 速度 类型
Fa0/1 PC DATA 已连接 1 全双工 100Mbps
Fa0/2 PC DATA 未连接 1 自动 自动
Fa0/3 禁用 1 自动 自动 10/100BaseTX nan
Fa0/4 已连接 1 全双工 100Mbps 10/100BaseTX nan
Fa0/5 KRONOS 未连接 1 自动 自动 10/100BaseTX
Fa0/6 KRONOS 未连接 1 自动 自动 10/100BaseTX

这是我的代码

from netmiko import ConnectHandler
import pandas as pd

def get_ip_address():
    ip_address_request = input("Please enter the IP address of the device: ")
    return ip_address_request

ip_address = get_ip_address()
switch = {
        "device_type":"cisco_ios",
        "ip": ip_address,
        'username': 'redacted',
        'password': 'redacted',        
}

net_connect = ConnectHandler(**switch)
prompt = net_connect.find_prompt()
hostname = prompt[:-1]
status = net_connect.send_command("Show interface status", use_textfsm=True)
net_connect.disconnect()

sum_status = []
lines = status.strip().split('\n')
headers = lines[0].split()

for line in lines[1:]:
    values = line.split()
    entry = {}
    for i, header in enumerate(headers):
        if i < len(values):
            entry[header] = values[i] 
    sum_status.append(entry)  


status_df = pd.DataFrame(sum_status)
status_df.reset_index(inplace=True, drop=True)

pd.set_option('display.max_colwidth', None)
status_df.loc[:, 'Name'] = status_df['Name'].fillna('')
print(status_df.to_string(index=False))

1 个回答

0

这个问题其实和pandas没什么关系。真正的问题在于原始输入中可能有空字段。所以这个写法是不对的:

for line in lines[1:]:
    values = line.split()  
    # generates bad input if there are empty fields
    # also generates bad input when a field contains a space

要解决这个问题,你需要逐行检查输入,看看是否有空字段或者只有空格的字段。例如,如果“状态”这个字段总是“disabled”或者“connected”,那么你可以用这个作为参考来确定列的位置。

为了验证我的说法是否正确,你可以加上这个:

headers = lines[0].split()
num_headers = len(headers)

for line in lines[1:]:
    values = line.split()
    assert len(values) == num_headers  
    # this raise an AssertionError for some lines

从netmiko的角度来看,问题在于你设置了use_textfsm=True这个标志——这其实是好的,应该能得到结构化的输出,也就是一个字典列表,可以直接加载到pandas的数据框中,而不需要拆分或解析行——但实际上输出却是一个简单的字符串。这显然是因为没有安装正确的ntc-template。有关这个的文档可以查看: https://pynet.twb-tech.com/blog/netmiko-and-textfsm.html

撰写回答