在使用“subprocess.check_output”时,如何正确引用python中的bash命令?

在使用“subprocess.check_output”时,如何正确引用python中的bash命令?,python,bash,shell,time,subprocess,Python,Bash,Shell,Time,Subprocess,我试图在python中运行并读取time命令的输出。问题是time命令在/bin/sh和/bin/bash中的工作方式不同,如下所示: sh $ time ls .. 0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3856maxresident)k 0inputs+0outputs (0major+305minor)pagefaults 0swaps 而/bin/bash版本是: bash $ time ls .. r

我试图在python中运行并读取
time
命令的输出。问题是
time
命令在
/bin/sh
/bin/bash
中的工作方式不同,如下所示:

sh $ time ls
..
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3856maxresident)k
0inputs+0outputs (0major+305minor)pagefaults 0swaps
/bin/bash
版本是:

bash $ time ls
..

real    0m0.003s
user    0m0.000s
sys     0m0.000s
我需要后者,因为它比前者更精确

因此,我试图在
check\u output
中用
bash-c'
包装命令,但它给出了一个错误:

>>> s.check_output(["bash", "-c", "'time ls'"])                                  
bash: time ls: command not found
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['bash', '-c', "'time ls'"]' returned non-zero exit status 127
最后,当我使用
executable
参数而不是包装时,输出不会捕获任何内容:

>>> s.check_output(['time', 'ls'], shell=True, executable='/bin/bash')

real    0m0.000s
user    0m0.000s
sys     0m0.000s

如何执行此操作?

使用
/bin/sh
时间ls
运行外部程序
/usr/bin/time
(您的路径可能会有所不同),然后运行
ls
,并将计时信息报告到其标准错误

对于
/bin/bash
time
是一个关键字,它指示
bash
shell本身将执行
ls
的计时信息报告为标准错误。因此,您需要将shell的标准错误(而不是命令)重定向到标准输出,以便
check\u output
可以捕获它。有点难看,但是

s.check_output('exec 2>&1; time ls >/dev/null 2>&1', executable='/bin/bash', shell=True)

应该有用。
exec 2>&1
是允许
检查输出的部分
捕获任何内容。
ls
之后的重定向用于从捕获的内容中删除
ls
的输出;如果需要命令输出,也可以删除它们。

使用
/bin/sh
time ls
运行外部程序
/usr/bin/time
(您的路径可能会有所不同),然后运行
ls
,并将计时信息报告到其标准错误

对于
/bin/bash
time
是一个关键字,它指示
bash
shell本身将执行
ls
的计时信息报告为标准错误。因此,您需要将shell的标准错误(而不是命令)重定向到标准输出,以便
check\u output
可以捕获它。有点难看,但是

s.check_output('exec 2>&1; time ls >/dev/null 2>&1', executable='/bin/bash', shell=True)

应该有用。
exec 2>&1
是允许
检查输出的部分
捕获任何内容。
ls
之后的重定向用于从捕获的内容中删除
ls
的输出;如果需要命令输出,也可以将其删除。

错误是由于在将列表证明为命令行时不应引用字符串。事实上:

>>> s.check_output(['bash', '-c', "time ls"])

real    0m0.002s
user    0m0.000s
sys     0m0.000s
'some content produced by ls'
不会引发任何异常,而:

>>> s.check_output(['bash', '-c', "'time ls'"])
bash: time ls: comando non trovato
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/subprocess.py", line 586, in check_output
    raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command '['bash', '-c', "'time ls'"]' returned non-zero exit status 127
引用
'time ls'
使
bash
搜索程序
time ls
,而不是以
ls
作为参数运行的程序
time

为什么不需要引用?简单:字符串列表指定如何拆分命令行。将
“time ls”
放在列表的单个元素中已经提供了所需的“quoting”


至于如何获得所需的输出,由于
bash
时间
stderr
上输出,解决方案是将
stderr
重定向到
stdout
(并删除
ls
输出)


该错误是由于在将列表证明为命令行时不应引用字符串而导致的。事实上:

>>> s.check_output(['bash', '-c', "time ls"])

real    0m0.002s
user    0m0.000s
sys     0m0.000s
'some content produced by ls'
不会引发任何异常,而:

>>> s.check_output(['bash', '-c', "'time ls'"])
bash: time ls: comando non trovato
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/subprocess.py", line 586, in check_output
    raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command '['bash', '-c', "'time ls'"]' returned non-zero exit status 127
引用
'time ls'
使
bash
搜索程序
time ls
,而不是以
ls
作为参数运行的程序
time

为什么不需要引用?简单:字符串列表指定如何拆分命令行。将
“time ls”
放在列表的单个元素中已经提供了所需的“quoting”


至于如何获得所需的输出,由于
bash
时间
stderr
上输出,解决方案是将
stderr
重定向到
stdout
(并删除
ls
输出)