Pandas中的数据跳到其他单元格
我正在尝试从网络交换机获取show interface status的信息,并把这些数据放到Pandas中(我未来还有其他计划使用这些数据)。
当我登录到网络交换机并自己运行命令时,得到了如下输出:
端口 | 名称 | 状态 | 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时,我遇到了两个问题。输出本身是正常的,但看起来像是格式或表格的问题。
- 如果某一行的名称单元格是空的,其他单元格会向左移动。(例如:Fa0/3和Fa0/4)
- 如果名称单元格中有两个或更多单词并且有空格,每个单词会填充到单元格的右侧,这样会导致数据无法使用。(例如:Fa0/1和Fa0/2)
这是我从代码中得到的输出.. 我也把它放成表格形式,下面可以看到两个表格之间有一些不一致。
端口 | 名称 | 状态 | 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