子流程 - 显示X行输出

时间:2014-02-08 22:24:09

标签: python subprocess output

我调用一个运行可执行文件的子进程,输出类似于:

Header
some text
some text
--------------------------------
Progress:
***           | 30%
I want this line too

我想要最后三行,但不是前一行。进展自我更新,我也希望有。

我目前正在做:

print subprocess.call('program {options}'.format(options=options), shell=True)

有没有简单的方法来实现这一目标?

1 个答案:

答案 0 :(得分:1)

call方法是Popen的包装器,它等待程序完成,这可能不是你想要的。相反,您需要使用Popen并从中读取stdout

答案取决于您正在使用的程序,或更具体,它如何更新终端。这是一个解决方案,它可以让您了解如何实现这一目标。你可能需要调整它。
例如,在我的示例中,仅实际更新了进度条本身。您的示例可能会更新更多行...

#!/usr/bin/env python2

from __future__ import print_function
import subprocess

proc = subprocess.Popen(['./out.py'], shell=True,
    stdout=subprocess.PIPE)

# Discard first 4 lines
for i in range(4): proc.stdout.readline()

# First set of output
output = ''.join([ proc.stdout.readline() for i in range(3) ])
print(output.strip())
print('\n\n')

# Only one line is updated now
while True:
    output = proc.stdout.readline()

    print(output.strip().replace('\x1b[1A', ''))

作为参考,这里是进度栏的out.py

#!/usr/bin/env python2

from __future__ import print_function
import time, sys

print('Header')
print('some text')
print('some text')
print('-' * 40)
print('Progress:')
print('')
print('I want this line too')

sys.stdout.write('\x1b[1A' * 2)
i = 1
while True:
        if i > 40: break

        print('\r', '*' * i, sep='')
        sys.stdout.write('\x1b[1A')
        sys.stdout.flush()
        i += 1
        time.sleep(2)

奖金提示

此外,您可能希望将subprocess方法与列表一起使用,如下所示:

subprocess.call(['ls', '-l', dir], shell=True)

原因是列表中的参数将被转义,即使它们包含空格,换行符或任何其他意外字符,它们仍然可以工作。如果您使用shell=True,这尤其危险。如果由于某种原因无法将参数作为列表传递,请务必使用shlex模块。