如何让Python脚本中的语句像在交互式shell中执行一样?

0 投票
3 回答
1259 浏览
提问于 2025-04-16 23:50

我有一个仪器,它连接在串口上。我在Windows XP上使用Python 3.2和pySerial模块。现在我遇到一个问题,就是当我执行一个脚本,这个脚本包含了一系列打开串口、配置串口、写入字符串和接收字符串的语句时,出现了一些问题。这些字符串要么是控制仪器的命令,要么是仪器的响应。

当我在Python的交互模式下(也就是在>>>后面)执行这些语句时,结果是我预期的,效果很好且正确。然而,当我在脚本中执行这些语句,无论是在交互模式还是在命令行中,我得到的结果却不如意。脚本中的语句和我在交互模式下使用的是一样的。

为什么会出现这种奇怪的情况?我该如何修改脚本,让它的表现和交互模式一样呢?

def read(comport):

    wrt_str=b'movt 3000'+b'\r\n'
    ret_str=comport.write(wrt_str)

    wrt_str=b'scan'+b'\r\n'
    ret_str=comport.write(wrt_str)

    rsp_str=comport.readlines() #########1

    wrt_str=b'hllo'+b'\r\n'
    ret_str=comport.write(wrt_str)

    rsp_str=comport.readlines()#########2

问题出在上面带有#######的几行。在交互模式下,第一个地方有大约1秒的延迟,第二个地方有9秒的延迟。这个时候我能得到正确的响应。然而,如果我执行上面的脚本,就没有任何延迟,结果却是错误的(垃圾数据)。我在串口设置中将读取超时设置为0,像这样:

comport.timeout=0

所以串口应该处于阻塞模式,这样它才能等待行结束或文件结束。

更新(2011年8月19日)

我对几天前发的原始帖子有了更新。我想我知道问题出在哪里了,想看看有没有人能提供解决方案:

在每个语句后面加上“print”和“time.sleep(delay)”后,我发现当脚本运行时,它似乎在绕过pyserial的语句,比如“comport.write(..)”或“comport.readlines(...)”,而这些pyserial命令正在执行(看起来像是在等待,串口的速度比较慢)。举个例子,当我在Python的交互式环境中执行所有语句时,如果前一个语句没有返回,我就无法输入并运行新的语句。比如说,如果comport.readlines()没有返回,我就不能输入并运行下一个comport.write(...)的语句。然而,在运行的脚本中,如果comport.readlines()正在忙着读取,下一条语句仍然会执行,如果下一条语句恰好是comport.write(),这就会中断读取。

有没有办法强制Python脚本按顺序执行呢?

3 个回答

0

试着在每个 comport.write 之后加一个暂停(比如用 time.sleep(1)),这样可以给设备一些时间来响应每个命令,然后再去查看响应。

正如 HYRY 提到的,把 timeout 设置为 0 会立即返回,所以它并不会像你想的那样工作。此外,当你逐行输入命令时,每输入一行都会有一些延迟。而在脚本中执行这些命令时,它们之间几乎没有间隔。

1

我建议把每个命令字符串放到自己的函数里,然后一个接一个地调用这些函数,中间加一些暂停。

另外,如果你知道输出数据字符串的长度,可以设置你的 read()readlines() 在读取到指定的字节数后停止,或者如果你的读取字符串长度不固定,也可以设置一个任意的数字来停止。

2

我看了pyserial的文档:

timeout = None: wait forever
timeout = 0: non-blocking mode (return immediately on read)
timeout = x: set timeout to x seconds (float allowed)

如果你把comport.timeout设置为0,那么readlines()会立刻返回结果。试着把comport.timeout设置为10吧。

撰写回答