Python,subprocess.check_call()和管道重定向

时间:2014-09-04 01:16:55

标签: python shell

为什么我在执行此命令时会获得文件列表?

subprocess.check_call("time ls &>/dev/null", shell=True)

如果我要粘贴

time ls &>/dev/null
进入控制台,我会得到时间。 操作系统是Linux Ubuntu。

2 个答案:

答案 0 :(得分:0)

在类似debian的系统上,默认shell为dash,而不是bashDash不支持&>快捷方式。要仅获取子进程返回代码,请尝试:

subprocess.check_call("time ls >/dev/null 2>&1", shell=True)

要获取子流程返回代码和时间信息而不是目录列表,请使用:

subprocess.check_call("time ls >/dev/null", shell=True)

当然,减去子进程返回代码,这与您在dash命令提示符下看到的行为相同。

答案 1 :(得分:0)

Python版本在sh下运行,但控制台版本在您的默认shell中运行,可能是bashdash。 (您的sh实际上可能是在POSIX兼容模式下运行的不同shell,但这并没有任何区别。)

bashdash都有内置time个功能,但sh没有,所以你得到/usr/bin/time,这是一个正常的程序。最重要的区别是time内置函数不是作为具有自己的独立stdout和stderr的子进程运行。

此外,shbashdash都有不同的重定向语法。


但是你首先想要做的事情似乎是错误的,而且你在控制台上获得了幸运,因为两个错误正在取消。

你想摆脱ls的标准输出但是保持time的标准,但那不是你要求的。您正在尝试重定向stdout和stderr:>&在实际支持它的任何shell上的含义。

那你为什么还得到time stderr? (a)您的默认shell不支持>&,或者(b)您使用内置而不是程序,并且您没有重定向shell本身的stderr ,或者(c)以上两者。


如果你真的想在Python中做同样的事情,完全相同的错误以完全相同的方式取消,你可以手动运行你的默认shell而不是shell=True。根据它的工作原因,可能是:

subprocess.check_call([os.environ['SHELL'], '-c', 'time ls &> /dev/null'])

或者这个:

subprocess.check_call('{} -c time ls &> /dev/null'.format(os.environ(SHELL), shell=True)

但实际上,你为什么要这样做呢?如果要重定向stdout而不是stderr,请写下:

subprocess.check_call('time ls > /dev/null', shell=True)

或者,更好的是,你为什么甚至首先使用shell?

subprocess.check_call(['time', 'ls'], stdout=subprocess.devnull)