出于某种原因,当我从终端运行“time。/”时,我得到这种格式:
real 0m0.090s user 0m0.086s sys 0m0.004s
但是当我在Python 2.7.6中执行相同的命令时:
result = subprocess.Popen("time ./<binary>", shell = True, stdout = subprocess.PIPE)
...我在print(result.stderr)
:
0.09user 0.00system 0:00.09elapsed
有什么方法可以强制第一个(真实,用户,系统)格式?
答案 0 :(得分:3)
来自man time
文档:
实用程序完成后,时间会将经过的总时间,系统开销所消耗的时间以及执行实用程序所用的时间写入标准错误流。
大胆强调我的。您正在捕获 stdout 流,而不是stderr
流,因此您看到的任何输出必须是其他内容损坏您的Python stderr流的结果。
捕获stderr
:
proc = subprocess.Popen("time ./<binary>", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
然后stderr
变量保存time
命令输出。
如果这继续产生相同的输出,则/bin/bash
实现具有内置time
命令,该命令将覆盖/usr/bin/time
版本(可能在一行上输出所有内容)。你可以通过告诉Python运行它来强制使用bash内置:
proc = subprocess.Popen("time ./<binary>", shell=True, executable='/bin/bash',
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
答案 1 :(得分:3)
首先:Martijn Pieters' answer对于需要捕获time
的{{1}}而不是stderr
是正确的。
此外,至少在像3.1这样的旧版本的Python上,subprocess.Popen
object包含几个可以被视为“输出”的东西。尝试stdout
只会导致:
print
如果以后的版本是<subprocess.Popen object at 0x2068fd0>
- 能够,他们必须对其内容进行一些处理,可能包括修改输出。
print
对象 Popen
对象有一个stderr
field,它是一个可读的文件对象。您可以像其他任何类似文件的对象一样 Popen
,但不建议这样做。引用大的粉红色security warning:
警告
使用
communicate()
而不是.stdin.write
,.stdout.read
或.stderr.read
来避免由于任何其他操作系统管道缓冲区填满并阻止子进程而导致的死锁。
要打印read
的内容,您必须:
communicate()
使用子流程,将2元组分配给本地变量(Popen
,stdout
)。
将变量的内容转换为字符串---默认情况下,它是stderr
对象,就像“文件”已在二进制模式下打开一样。
下面是一个很小的程序,它打印一个shell命令的bytes
输出而不用修改(不计算从ASCII转换为Unicode并返回)。
stderr
此输出位于旧的Fedora Linux系统上,运行#!/usr/bin/env python3
import subprocess
def main():
result = subprocess.Popen(
'time sleep 0.2',
shell=True,
stderr=subprocess.PIPE,
)
stderr = result.communicate()[1]
stderr_text = stderr.decode('us-ascii').rstrip('\n')
#print(stderr_text) # Prints all lines at once.
# Or, if you want to process output line-by-line...
lines = stderr_text.split('\n')
for line in lines:
print(line)
return
if "__main__" == __name__:
main()
且bash
设置为LC_ALL
:
real 0m0.201s user 0m0.000s sys 0m0.001s
请注意,您需要在我的脚本的"C"
行周围添加一些错误处理...据我所知,stderr_text = stderr.decode(...)
根据本地化,环境变量等发出非ASCII字符
time
您可以使用universal_newlines
option to Popen
保存一些解码样板。它自动执行从universal_newlines
到bytes
的转换:
如果 universal_newlines 为
strings
,则这些文件对象将使用universal newlines返回的编码以locale.getpreferredencoding(False)
模式作为文本流打开。 [...]
True
请注意,我仍然需要手动剥离最后一个def main_universal_newlines():
result = subprocess.Popen(
'time sleep 0.2',
shell=True,
stderr=subprocess.PIPE,
universal_newlines=True,
)
stderr_text = result.communicate()[1].rstrip('\n')
lines = stderr_text.split('\n')
for line in lines:
print(line)
return
以完全匹配shell的输出。