65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Python 通过 Pyserial 与 Cisco 设备交互

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2015年1月31日

GPL3

2分钟阅读

viewsIcon

23658

为了我的最新项目,我想通过控制台端口使用 Python 程序与 Cisco 设备进行串行通信。

为了我的最新项目,我想通过控制台端口使用 Python 程序与 Cisco 设备进行串行通信。这并不复杂,但花了我一些时间才拼凑出能正常工作的代码,我想与大家分享。  以下是代码

import serial
from time import sleep

# Open the serial port. The settings are set to Cisco default.
serial_port = serial.Serial(2, baudrate=9600, timeout=None, parity=serial.PARITY_NONE, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE, xonxoff=False)

# Make sure there is not any lingering input - input in this case being data waiting to be received
serial_port.flushInput()

print(serial_port.name)

serial_port.write("\n".encode())

serial_port.write("?".encode())

bytes_to_read = serial_port.inWaiting()

# Give the line a small amount of time to receive data
sleep(.5)

# 9600 baud is not very fast so if you call serial_port.inWaiting() without sleeping at all it will likely just say
# 0 bytes. This loop sleeps 1 second each iteration and updates bytes_to_read. If serial_port.inWaiting() returns a
# higher value than what is in bytes_to_read we know that more data is still coming in. I noticed just by doing a ?
# command it had to iterate through the loop twice before all the data arrived.
while bytes_to_read < serial_port.inWaiting():
    bytes_to_read = serial_port.inWaiting()
    sleep(1)

# This line reads the amount of data specified by bytes_to_read in. The .decode converts it from a type of "bytes" to a
# string type, which we can then properly print.
data = serial_port.read(bytes_to_read).decode()
print(data)

# This is an alternate way to read data. However it presents a problem in that it will block even after there is no more
# IO. I solved it using the loop above.
# for line in serial_port:
# print(line)

serial_port.close()

第一行打开一个供我们使用的串行端口对象。您唯一需要更改的是端口号,它是第一个参数。 在我的例子中,我的控制台电缆连接到 COM3,这是第三个端口。 像往常一样,它们从 0 开始计数,所以我的端口是 # 2。 其余的您可以保持不变,我已经将其配置为 Cisco 的默认设置。 请记住,如果您更改了 Cisco 设备上的波特率,您也需要在这里更改波特率,就像正常的终端一样。

# Open the serial port. The settings are set to Cisco default.
serial_port = serial.Serial(2, baudrate=9600, timeout=None, parity=serial.PARITY_NONE, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE, xonxoff=False)

接下来的两行清除接收队列中任何我们不感兴趣的残留输入,然后打印我们正在使用的端口名称(以防您需要它)。

# Make sure there isn't any lingering input - input in this case being data waiting to be received
serial_port.flushInput()

print(serial_port.name)

现在我们与 Cisco 设备交互。 当您首次启动 IOS 时,您必须按 Enter 键才能获得命令提示符。 这正是

serial_port.write("\n".encode())

所做的事情。 .encode() 是必要的,因为 .write() 命令期望的是字节类型。 encode() 方法使用默认字符编码将我们的字符串转换为字节。 在我的计算机上,它是 UTF-8。 下一行是一个概念验证。 为了测试我的程序,我只是让它读取帮助命令的内容。

serial_port.write("?".encode())

接下来的几行是程序的核心。 循环上方的注释很好地解释了正在发生的事情。 inWaiting() 命令返回接收队列中等待的字节数。

# Give the line a small amount of time to receive data
sleep(.5)

# 9600 baud is not very fast so if you call serial_port.inWaiting() without sleeping at all it will likely just say
# 0 bytes. This loop sleeps 1 second each iteration and updates bytes_to_read. If serial_port.inWaiting() returns a
# higher value than what is in bytes_to_read we know that more data is still coming in. I noticed just by doing a ?
# command it had to iterate through the loop twice before all the data arrived.
while bytes_to_read < serial_port.inWaiting():
    bytes_to_read = serial_port.inWaiting()
    sleep(1)

# This line reads the amount of data specified by bytes_to_read in. The .decode converts it from a type of "bytes" to a
# string type, which we can then properly print.
data = serial_port.read(bytes_to_read).decode()
print(data)

输出应该如下所示

Cisco-1700>?
Exec commands:
access-enable Create a temporary Access-List entry
access-profile Apply user-profile to interface
clear Reset functions
connect Open a terminal connection
crypto Encryption related commands.
disable Turn off privileged commands
disconnect Disconnect an existing network connection
enable Turn on privileged commands
exit Exit from the EXEC
help Description of the interactive help system
lock Lock the terminal
login Log in as a particular user
logout Exit from the EXEC
modemui Start a modem-like user interface
mrinfo Request neighbor and version information from a multicast
router
mstat Show statistics after multiple multicast traceroutes
mtrace Trace reverse multicast path from destination to source
name-connection Name an existing network connection
pad Open a X.29 PAD connection
ping Send echo messages
--More--

最后一行关闭串行端口。

serial_port.close()

希望这能帮助您节省一些时间。

© . All rights reserved.