为什么strip()能解决这个pexpect脚本问题?
我有一个对象。
这个对象里面有一个叫做 connect()
的方法,它会启动一个 pexpect 进程。
这个启动的进程是一个自定义的串口接口。启动时,这个工具会打印出一个可以连接的串口设备菜单,像这样:
libftdi device (0): A6005jpt libftdi device (1): acFX9DQf Serial device (a) : /dev/cu.Bluetooth-PDA-Sync Select a device by its letter (^D to abort):
我的 connect()
方法会根据给定的设备名称(比如 'acFX9DQf')来决定传递哪个数字: (self.connection 是 pexpect 启动的进程)
USBSERIAL_DEVICE_NAME = "acFX9DQf" try: while self.connection.expect(['libftdi device \(([0-9])\): (.*)','Serial device']) == 0: if self.connection.match.group(2).strip() == USBSERIAL_DEVICE_NAME: # do stuff except: # do stuff
现在,我的问题是我在主逻辑中多次调用 connect()
和 kill()
这个进程,有时候在某次调用中,connect()
会意外地抛出一个 pexpect.TIMEOUT
异常。
例如,当我在逻辑中添加以下调试语句时,像这样:
USBSERIAL_DEVICE_NAME = "acFX9DQf" try: while self.connection.expect(['libftdi device \(([0-9])\): (.*)','Serial device'], timeout=10) == 0: print "MATCHED A DEVICE LINE!" if self.connection.match.group(2).strip() == USBSERIAL_DEVICE_NAME: print "MATCHED THE DESIRED USBSERIAL..."
...我在多次调用 connect()
时得到这样的输出:
libftdi device (0): A6005jpt MATCHED A DEVICE LINE! libftdi device (1): acFX9DQf MATCHED A DEVICE LINE! MATCHED THE DESIRED USBSERIAL... Serial device (a) : /dev/cu.Bluetooth-PDA-Sync Select a device by its letter (^D to abort): 1
...然后,我的某次 connect()
调用会意外地出现....
libftdi device (0): A6005jpt MATCHED A DEVICE LINE! libftdi device (1): acFX9DQf Serial device (a) : /dev/cu.Bluetooth-PDA-Sync Select a device by its letter (^D to abort): MATCHED A DEVICE LINE! <<EXCEPTION>>
但是,如果我把代码改成这样:
try: while self.connection.expect(['libftdi device \(([0-9])\): (.*)','Serial device'], timeout=10) == 0: devicename = self.connection.match.group(2).strip() if devicename == USBSERIAL_DEVICE_NAME: # do stuff
我的问题就解决了!我可以反复运行它,完全没有问题 - 没有异常,也没有任何其他问题。
那么,这到底是怎么回事呢?我甚至不知道从哪里开始解决这个问题。
1 个回答
我猜你遇到了一个 TIMEOUT
的错误。根据输出中“匹配到设备行!”这条消息的位置,我猜测 spawn
实例在测试匹配时有多行内容。当 pexpect 编译正则表达式时,它会设置 re.DOTALL,这样 .*
就会包括换行符和其他行。这导致对 USBSERIAL_DEVICE_NAME
的测试失败,循环继续进行下一次迭代。接下来的 expect
调用会被阻塞,因为没有额外的输入,这样你就会遇到超时。
要解决这个问题,你可以传入自己编译的正则表达式(不带 re.DOTALL
标志),或者修改 .*
,让它明确不匹配换行符(例如 \S*
)。
至于为什么把匹配的结果存储在一个变量中似乎能解决问题,我只能猜这引入了一个微妙的时间变化,防止 expect
同时接收到多行输入。