Python3.6使用pexpect spawn触发TypeError问题求助
首先,明确你的核心场景与问题:你在CentOS 7系统的笔记本上,用Python 3.6.4编写Telnet自动化脚本时,遇到了TypeError: must be str, not bytes的错误,同时不确定自定义函数的语法是否符合Python 3规范。下面一步步帮你解决:
原脚本与错误信息
你的Telnet自动化脚本
#!/usr/local/lib python3.6 import pexpect import sys import re def dologin(child): # Enter User Name child.expect ('login:') child.sendline ('admin') # Enter Password child.expect ('Password:') child.sendline ('123') return def doprepcommands(child): # Enter config prompt child.expect ('NOS/27179080475072>') child.sendline ('config') # Issue command child.expect ('NOS/27179080475072/DEBUG/Config>') child.sendline ('show vlan') child.expect ('NOS/27179080475072/DEBUG/Config>') child.sendline ('exit') child.expect ('NOS/27179080475072/DEBUG>') child.sendline ('exit') child.expect ('NOS/27179080475072') child.sendline ('exit') return # Spawn the telnet session child = pexpect.spawn ('telnet 192.168.1.254') # Display progress on screen child.logfile = sys.stdout dologin(child) doprepcommands(child)
运行时的错误输出
================= RESTART: /home/aricent/Siva/test_debug.py ================= Traceback (most recent call last): File "/home/Siva/test_debug.py", line 37, in <module> dologin(child) File "/home/Siva/test_debug.py", line 8, in dologin child.expect ('login:') File "/usr/local/lib/python3.6/site-packages/pexpect/spawnbase.py", line 341, in expect timeout, searchwindowsize, async_) File "/usr/local/lib/python3.6/site-packages/pexpect/spawnbase.py", line 369, in expect_list return exp.expect_loop(timeout) File "/usr/local/lib/python3.6/site-packages/pexpect/expect.py", line 111, in expect_loop incoming = spawn.read_nonblocking(spawn.maxread, timeout) File "/usr/local/lib/python3.6/site-packages/pexpect/pty_spawn.py", line 485, in read_nonblocking return super(spawn, self).read_nonblocking(size) File "/usr/local/lib/python3.6/site-packages/pexpect/spawnbase.py", line 179, in read_nonblocking self._log(s, 'read') File "/usr/local/lib/python3.6/site-packages/pexpect/spawnbase.py", line 126, in _log self.logfile.write(s) TypeError: must be str, not bytes
问题分析与修正
1. 核心错误:TypeError: must be str, not bytes
在Python 3中,sys.stdout默认只能接收**字符串(str)类型的数据,但pexpect.spawn对象输出的是字节流(bytes)**类型,直接把sys.stdout赋值给child.logfile就会触发类型不匹配的错误。
解决方法很简单,改用sys.stdout.buffer(Python 3中专门处理字节流的标准输出对象):
child.logfile = sys.stdout.buffer
2. 脚本中的其他潜在问题
Shebang行错误:原脚本第一行
#!/usr/local/lib python3.6是错误的,Python解释器通常位于/usr/local/bin/目录下,正确的Shebang应该是:#!/usr/local/bin/python3.6给脚本添加执行权限(
chmod +x test_debug.py)后,就能直接运行了。提示符中的HTML实体错误:原脚本里的
NOS/27179080475072>是HTML转义后的>符号,实际设备提示符是>,所以要把所有>替换成>,否则pexpect.expect会匹配不到提示符,最终触发超时错误。函数语法合规性:你的
dologin和doprepcommands函数语法完全符合Python 3规范,函数定义、参数传递、return语句都没有问题,这点可以放心。
修正后的完整脚本
#!/usr/local/bin/python3.6 import pexpect import sys import re def dologin(child): # Enter User Name child.expect('login:') child.sendline('admin') # Enter Password child.expect('Password:') child.sendline('123') return def doprepcommands(child): # Enter config prompt child.expect('NOS/27179080475072>') child.sendline('config') # Issue command child.expect('NOS/27179080475072/DEBUG/Config>') child.sendline('show vlan') child.expect('NOS/27179080475072/DEBUG/Config>') child.sendline('exit') child.expect('NOS/27179080475072/DEBUG>') child.sendline('exit') child.expect('NOS/27179080475072') child.sendline('exit') return # Spawn the telnet session child = pexpect.spawn('telnet 192.168.1.254') # Display progress on screen - 修正字节流输出问题 child.logfile = sys.stdout.buffer dologin(child) doprepcommands(child)
额外提示
如果后续遇到提示符匹配超时的问题,可以尝试:
- 给
expect方法添加timeout参数,比如child.expect('login:', timeout=30),延长等待时间; - 用正则表达式匹配提示符,比如用
child.expect(r'NOS/.*>')来匹配任意以NOS/开头、以>结尾的提示符,避免设备ID变化导致匹配失败。
内容的提问来源于stack exchange,提问作者Sivaprasath Kanakavel

