Python - 运行进程并等待输出

5
我想运行一个程序,等待它的输出,向其发送输入并重复此过程直到满足某个条件。
我找到的所有问题都是关于等待程序完成的,但这不是我的情况。该进程仍将继续运行,只是不会提供任何(新的)输出。
程序输出在stdout和日志文件中,可以使用其中任意一个。
使用Linux。
目前的代码:
import subprocess

flag = True
vsim = subprocess.popen(['./run_vsim'], 
                        stdin=subprocess.pipe,
                        shell=true, 
                        cwd='path/to/program')
while flag:
    with open(log_file), 'r') as f:
        for l in f:
            if condition:
                break
    vsim.stdin.write(b'do something\n')
    vsim.stdin.flush()
vsim.stdin.write(b'do something else\n')
vsim.stdin.flush()

目前,“做某事”输入在程序启动之前被发送多次。此外,在程序完成最后一次迭代的命令之前,日志文件就已经被读取了。这导致它缓冲了输入,因此在满足条件后,即使在条件已经达到后,它仍会继续执行命令,这是不合理的。
我可以在每个stdin.write之后使用time.sleep,但由于执行每个命令所需的时间是可变的,我需要使用比必要时间更长的时间,从而使python脚本变慢。这也是一个愚蠢的解决方案。
谢谢!

子进程是否会打印某种标准的“完成”消息来指示它已经完成处理?如果是这样,您可能可以使用 pexpect - Linuxios
你考虑过使用线程,多进程,或者asyncio吗? - wwii
这个过程是将数据倾倒到管道,还是滴滴答答地传输数据?当你获取数据时,如何确定已经全部获取?你是说这个进程永远不会终止吗? - wwii
@Linuxios 我不知道有没有,但我会调查一下。 - dramm
@wwii 我还没有,但我会阅读文档。我相当确定它是多线程的,如果不是的话,Python脚本将等待子进程运行(我可能错了,以前从未使用过线程)。 - dramm
@wwii 不确定你所说的“dribble”是什么意思。该过程将数据发送到sdtdout(管道)和日志文件。因此,如果它停止向stdout发送数据且日志文件未更改,则该进程正在等待新输入。使用当前代码,您可以说该进程永远不会终止(我等了几分钟,它仍在运行,因为有缓冲的输入)。也许,如果您将其视为运行脚本的Python(或其他语言)shell,然后等待新输入(可以是“运行更多内容”或“退出”),这可能会有所帮助。 - dramm
3个回答

0
如果您正在使用Python3,可以尝试更新您的代码以使用subprocess.run。它应该会等待您的任务完成并返回输出。

1
就像我在问题中所说的那样,任务进程仍在运行,只是因为正在等待输入,所以不会提供任何新的输出。 - dramm

0
截至2019年,您可以使用subprocess.getstatusoutput()运行进程并等待输出,例如:
import subprocess
args = "echo 'Sleep for 5 seconds' && sleep 5"
status_output = subprocess.getstatusoutput(args)
if status_output[0] == 0: # exitcode 0 means NO error
  print("Ok:", status_output[1])
else:
  print("Error:", status_output[1])

Python演示


来自Python 文档:

subprocess.getstatusoutput(_cmd_)

在shell中执行字符串cmd,使用Popen.check_output()并返回2元组(exitcode, output)。使用本地编码;有关更多详细信息,请参见常用参数的注释。

输出中的尾随换行符将被剥离。命令的退出代码可以解释为子进程的返回代码。例如:

>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
>>> subprocess.getstatusoutput('cat /bin/junk')
(1, 'cat: /bin/junk: No such file or directory')
>>> subprocess.getstatusoutput('/bin/junk')
(127, 'sh: /bin/junk: not found')
>>> subprocess.getstatusoutput('/bin/kill $$')
(-15, '')

-2

你可以使用命令而不是子进程。这里有一个使用ls命令的例子:

import commands 
status_output = commands.getstatusoutput('ls ./')
print status_output[0] #this will print the return code (0 if everything is fine)
print status_output[1] #this will print the output (list the content of the current directory)

从文档中得知:自2.6版本起已被弃用:在Python 3中已删除commands模块。请改用subprocess模块。问题带有python-3x标签。 - slackmart
它有Python标签 - Walid Da.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接