Python3.8搭配pexpect4.8时spawn对象before属性引用空值问题
根因分析
- 代码本身的逻辑存在不符合pexpect设计规则的部分:
before属性仅在expect()调用完成后才会更新为本次匹配到分隔符之前的所有缓冲区内容,你在sendline之后、expect之前打印的before是上一次expect执行后的残留值,本身不代表本次命令的输出内容。 - 高版本pexpect(4.3+)优化了
expect的匹配速度,会在shell回显、命令输出还没完全写入伪终端(PTY)缓冲区的时候,就提前匹配到了self.expList中的提示符,导致before只捕获到了终端控制序列,没有捕获到命令执行结果和回显。4.2.1版本的匹配速度较慢,刚好能等输出完全写入缓冲区再完成匹配,所以之前没有出现问题。你提供的异常字节串内容也可以验证这点:异常时before里只有回车、清行控制符、窗口标题设置序列,没有任何命令相关的有效内容。
解决方案
所有方案均兼容Python 3.8 + pexpect 4.8.0的环境,不需要降级版本:
- 方案1:
sendline后添加极短延迟再调用expect,给PTY预留缓冲区写入时间,0.05~0.2秒的延迟不会影响整体执行效率,修改示例如下:
self.conn.sendline(cmd) import time time.sleep(0.1) # 新增延迟行 index = self.conn.expect( self.expList, timeout = thisTimeout )
- 方案2:调整匹配逻辑,先匹配命令回显再匹配提示符,确保输出完全被捕获。可以把
expect拆分为两次调用,第一次匹配你输入的命令内容,第二次匹配原有提示符,两次捕获的before拼接起来就是完整输出。 - 方案3:
expect匹配完成后增加额外的非阻塞读逻辑,把缓冲区中还没被读取的剩余内容拼接到输出中,无需调整时序:
index = self.conn.expect( self.expList, timeout = thisTimeout ) # 新增缓冲区兜底读取逻辑 try: extra_out = self.conn.read_nonblocking(size=4096, timeout=0.1) output += extra_out.decode() except: # 无剩余内容时直接跳过即可 pass output += self.conn.before.decode()
内容的提问来源于stack exchange,提问作者lostdong12
相关产品推荐
相关产品推荐

