关于Python中pexpect的问题

1 投票
1 回答
3644 浏览
提问于 2025-04-16 08:10

我尝试使用 Python 的 pexpect 和 subprocess.Popen 来调用一个外部的长期后台进程(这个进程通过 socket 和外部应用程序进行通信),以下是一些细节。

  1. subprocess.Popen(launchcmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 这个方法很好用。我不需要做其他的事情。不过,因为我需要立即获取输出,所以我选择了 pexpect,以避免管道文件的缓冲问题。

  2. obj = pexpect.spawn(launchcmd, timeout=None) 在启动外部进程后,我使用一个单独的线程来执行 "readline",读取启动进程 "obj" 的输出,一切都正常。

  3. obj = pexpect.spawn(launchcmd, timeout=None) 在启动外部进程后,我没有做进一步的操作,也就是就让它在那里待着。虽然我可以通过 "ps -e" 命令找到这个启动的进程,但这个进程似乎被阻塞了,无法通过 socket 和其他应用程序进行通信。

好的,为了更具体一点,我放了一些示例代码来说明我的问题。

import subprocess
import pexpect
import os

t=1
while(True):
    if(t==1):
        background_process="./XXX.out"
        launchcmd = [background_process]
        #---option 3--------
        p=pexpect.spawn(launchcmd, timeout=None) # process launced, problem with socket.
        #---option 1--------
        p=subprocess.Popen(launchcmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # process launced, everything fine
        t=0 

有没有人能告诉我第三个选项有什么问题?如果是因为我没有使用单独的线程来处理输出,那为什么第一个选项在使用 subprocess.popen 时能正常工作?我怀疑 pexpect 在使用 socket 启动进程时可能有问题,但我不太确定,尤其是考虑到第二个选项运行得很好。

1 个回答

1

我觉得你把事情搞得太复杂了。

没错,使用pty来和后台进程沟通确实是个好主意,因为大多数应用程序都能识别tty/pty设备,并且会切换到使用无缓冲输出(或者至少是行缓冲输出)。

但是为什么要用pexpect呢?直接用Python的pty模块就行了。首先调用openpty来获取一些文件句柄,然后用Popen来启动进程。示例代码可以在下面这个问题中找到(带绿色勾的答案) Python运行一个守护子进程并读取标准输出

撰写回答