2012-01-23 75 views
10

我写了一个简单的Python脚本我的应用程序和一些预定义的快速命令喜欢做等如何异步获取子进程的标准输出数据?

我写了一个函数用于运行系统命令(Linux版):

def runCommand(commandLine): 
    print('############## Running command: ' + commandLine) 
    p = subprocess.Popen(commandLine, shell = True, stdout = subprocess.PIPE) 
    print (p.stdout.read().decode('utf-8')) 

一切运作良好,除了一几件事情:

  • 我使用的cmake 它的输出是彩色的。任何机会在输出中保存颜色?

  • 我可以看看过程完成后的输出。例如,使得运行很长一段时间,但是只有在完全编译后才能看到输出。如何异步执行它?

回答

12

我不知道有关的颜色,但在这里是如何轮询子的stdout一行在一个时间:

import subprocess 
proc = subprocess.Popen('cmake', shell=True, stdout=subprocess.PIPE) 
while proc.poll() is None: 
    output = proc.stdout.readline() 
    print output 

不要忘了从标准错误读为好,因为我敢肯定的cmake将在那里发布信息。

+0

好的,谢谢。有用。 – Ockonal

2

关于如何让你的程序的输出完成之前,应该能够做到这一点取代:

p.stdout.read 

有:

for line in p.stdout: 

关于如何保存有色输出,没有什么特别的。例如,如果行输出保存到文件中,则下一次执行cat <logfile>时,控制台将解释转义序列并按预期显示颜色。

+0

with'readline()'我在行中有一个数字而不是文本,怎么了? – Ockonal

+1

@Ockonal实际上,如果你使用for循环,就不需要使用'readline'。你可以找到两个策略的例子[这里](http://stackoverflow.com/q/2804543/183066)。 – jcollado

+0

其实'对于p.stdout中的行来说,在Python 2中并不是很好根据http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line#comment11236752_2813530 –

0

进行异步输出做这样的事情:http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

不知道你是否能捕捉到的彩色输出。如果你能得到逃脱的颜色代码,你可能会。

+0

如果我们得到颜色代码,终端会翻译它们。但问题在于,大多数应用程序会区分被连接到终端或被传送到另一个应用程序。说服这些应用程序仍然生成颜色代码的唯一方法是伪造接收应用程序(本例中为我们的python进程)实际上是tty而不是管道。说起来容易做起来难, –

4

您没有变色,因为cmake检测到它的stdout是否是终端,如果不是它不会为它自己的输出着色。一些程序给你一个强制着色输出的选项。不幸的是cmake没有,所以你在那里运气不好。除非你想自己修补cmake

大量的程序做到这一点,例如grep的:

# grep test test.txt 
test 
^ 
| 
|------- this word is red 

现在管它的猫:

# grep test test.txt | cat 
test 
^ 
| 
|------- no longer red 

grep选项--color=always强制色彩:

# grep test test.txt --color=always | cat 
test 
^ 
| 
|------- red again 
-1

值得关注这里是使用script命令作为伪终端升和作为TTY代替重定向(管)文件描述符来检测,见: bash command preserve color when piping

就像一个魅力...

如占该问题的例子简单地让script执行cmake

import subprocess 
proc = subprocess.Popen('script cmake', shell=True, stdout=subprocess.PIPE) 
while proc.poll() is None: 
    output = proc.stdout.readline() 
    print output 

这招骗cmake认为它正在从终端执行,并会产生你以后的ANSI糖果。

nJoy!

相关问题