为什么 strip() 修复了这个 pexpect 脚本?
我有一个对象。
该对象有一个 connect()
方法,该方法会生成一个 pexpect 进程。
生成的进程是一个自定义串行接口。启动时,该工具会打印要连接的串行设备的菜单,如下所示:
libftdi device (0): A6005jpt libftdi 设备 (1):acFX9DQf 串行设备(a):/dev/cu.Bluetooth-PDA-Sync 通过字母选择设备(^D 表示中止):
我的 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()
进程,有时,其中一次,连接()
决定意外地抛出 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 匹配设备系列! libftdi 设备 (1):acFX9DQf 匹配设备系列! 匹配所需的 USB 串口... 串行设备(a):/dev/cu.Bluetooth-PDA-Sync 按字母选择设备(^D 表示中止):1
...然后,我的一个 connect()
调用将意外地执行...
libftdi device ( 0): A6005jpt 匹配设备系列! libftdi 设备 (1):acFX9DQf 串行设备(a):/dev/cu.Bluetooth-PDA-Sync 按字母选择设备(^D 中止):匹配设备线! <>
但是,如果我将代码修改为:
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
我的问题就会消失!我可以重复运行它,不会出现任何问题 - 没有例外,没有任何问题。
那么这里到底发生了什么?我什至不知道从哪里开始解决这个问题。
I have an object.
This object has a connect()
method which spawns a pexpect process.
The process that's spawned is a custom serial interface. On launch, this tool prints a menu of serial devices to connect to, like so:
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):
My connect()
determines which number to pass based on a given devicename (e.g. 'acFX9DQf'): (self.connection is the pexpect spawn)
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
Now, my problem is that I connect()
/kill()
the process multiple times in my main logic and sometimes, one of those times, connect()
decides to throw a pexpect.TIMEOUT
exception, unexpectedly.
For example, when I add the following debug statements to my logic, like so:
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..."
...I get this output for many calls of 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
...then, one of my connect()
calls will unexpectedly do....
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>>
But, if I revise my code to this:
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
My problems go away! I can run it repeatedly and no problems will occur - no exceptions, no nothin'.
So wot in the heck is going on here? I'm not even sure where to begin with this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我猜您遇到了
TIMEOUT
异常。基于“匹配设备线!”的位置消息在输出中,我的假设是spawn
实例在测试匹配时有多行。当 pexpect 编译正则表达式时,它 设置re.DOTALL
,因此.*
包含换行符和附加行。这会导致针对USBSERIAL_DEVICE_NAME
的测试失败,并且循环将继续进行下一次迭代。下一次对expect
的调用会阻塞,因为没有额外的输入并且您会遇到超时。要解决此问题,您可以传入自己编译的正则表达式(它将缺少
re.DOTALL
标志)或更改.*
,使其明确与换行符不匹配(例如\S*
)。至于为什么将匹配的组存储在变量中似乎可以解决问题,我只能猜测这会引入微妙的时间变化,从而阻止对
expect
的调用同时接收多行输入。I'm guessing you're getting a
TIMEOUT
exception. Based on where the "MATCHED A DEVICE LINE!" message is in the output, my hypothesis is that thespawn
instance has multiple lines when it tests for a match. When pexpect compiles the regexes, it setsre.DOTALL
, so the.*
includes the newline and the additional lines. This causes the test againstUSBSERIAL_DEVICE_NAME
to fail and the loop continues its next iteration. The next call toexpect
blocks because there is no additional input and you get a timeout.To fix this, you can pass in your own compiled regexes (which will lack the
re.DOTALL
flag) or change the.*
so it explicitly doesn't match the newline (e.g.\S*
).As for why storing the matched group in a variable seems to fix things, I can only guess this introduces a subtle timing change that prevents the call to
expect
from receiving multiple lines of input at once.