Python 3.4.3 subprocess.Popen得到没有pipe道命令的输出?

我正在尝试将一个命令的输出分配给一个variables,而不是该命令的输出。 其原因在于,如果正在pipe理,正在讨论的命令会将未格式化的文本输出为输出,但如果正在从terminal运行,则会提供彩色格式的文本。 我需要得到这个颜色格式的文本。

到目前为止,我已经尝试了一些东西。 我已经尝试过Popen了:

output = subprocess.Popen(command, stdout=subprocess.PIPE) output = output.communicate()[0] output = output.decode() print(output) 

这可以让我打印输出,但它给了我input命令时得到的无格式输出。 这是有道理的,因为我在Python代码中将其pipe道化。 但是我很好奇,如果有一种方法可以将这个命令的输出直接分配给一个variables,而不需要运行pipe道本身的pipe道版本。

我也尝试了依赖于check_output的以下版本:

 output = subprocess.check_output(command) output = output.decode() print(output) 

再次,我得到相同的未格式化输出,命令返回时,命令是pipe道。

有没有办法获得格式化的输出,命令通常从terminal给出的输出,当它不被pipe道?

Solutions Collecting From Web of "Python 3.4.3 subprocess.Popen得到没有pipe道命令的输出?"

使用pexpect :

2.py:

 import sys if sys.stdout.isatty(): print('hello') else: print('goodbye') 

子:

 import subprocess p = subprocess.Popen( ['python3.4', '2.py'], stdout=subprocess.PIPE ) print(p.stdout.read()) --output:-- goodbye 

Pexpect的:

 import pexpect child = pexpect.spawn('python3.4 2.py') child.expect(pexpect.EOF) print(child.before) #Print all the output before the expectation. --output:-- hello 

这里是用grep --colour=auto

 import subprocess p = subprocess.Popen( ['grep', '--colour=auto', 'hello', 'data.txt'], stdout=subprocess.PIPE ) print(p.stdout.read()) import pexpect child = pexpect.spawn('grep --colour=auto hello data.txt') child.expect(pexpect.EOF) print(child.before) --output:-- b'hello world\n' b'\x1b[01;31mhello\x1b[00m world\r\n' 

是的,你可以使用pty模块 。

 >>> import subprocess >>> p = subprocess.Popen(["ls", "--color=auto"], stdout=subprocess.PIPE) >>> p.communicate()[0] # Output does not appear in colour 

pty

 import subprocess import pty import os master, slave = pty.openpty() p = subprocess.Popen(["ls", "--color=auto"], stdout=slave) p.communicate() print(os.read(master, 100)) # Print 100 bytes # Prints with colour formatting info 

从文档注意:

由于伪终端处理是高度依赖于平台的,因此只有Linux才能执行代码。 (Linux代码应该在其他平台上工作,但还没有经过测试。)

一个阅读整个输出到最后的美丽方式不是一回事:

 def num_bytes_readable(fd): import array import fcntl import termios buf = array.array('i', [0]) if fcntl.ioctl(fd, termios.FIONREAD, buf, 1) == -1: raise Exception("We really should have had data") return buf[0] print(os.read(master, num_bytes_readable(master))) 

编辑:一次获得内容的更好的方式感谢@Antti Haapala:

 os.close(slave) f = os.fdopen(master) print(f.read()) 

编辑:人们是正确的指出,如果进程产生一个大的输出,这将死锁,所以@Antti Haapala的答案是更好的。

一个正在运行的polyglot示例(对于Python 2和Python 3来说是相同的)使用pty

 import subprocess import pty import os import sys master, slave = pty.openpty() # direct stderr also to the pty! process = subprocess.Popen( ['ls', '-al', '--color=auto'], stdout=slave, stderr=subprocess.STDOUT ) # close the slave descriptor! otherwise we will # hang forever waiting for input os.close(slave) def reader(fd): try: while True: buffer = os.read(fd, 1024) if not buffer: return yield buffer # Unfortunately with a pty, an # IOError will be thrown at EOF # On Python 2, OSError will be thrown instead. except (IOError, OSError) as e: pass # read chunks (yields bytes) for i in reader(master): # and write them to stdout file descriptor os.write(1, b'<chunk>' + i + b'</chunk>') 

许多程序在检测到没有直接连接到终端时会自动关闭彩色打印代码。 许多程序将有一个标志,所以你可以强制颜色输出。 您可以将此标志添加到您的流程调用中。 例如:

 grep "search term" inputfile.txt # prints colour to the terminal in most OSes grep "search term" inputfile.txt | less # output goes to less rather than terminal, so colour is turned off grep "search term" inputfile.txt --color | less # forces colour output even when not connected to terminal 

被警告。 实际的颜色输出由终端完成。 终端解释特殊字符空格代码,并相应地更改文本颜色和背景颜色。 如果没有终端来解释颜色代码,您将只能看到黑色的文本,这些转义代码贯穿始终。