2012-07-15 87 views
24

我想将子进程的stderr输出重定向到stdout。常数STDOUT应该这样做,不是吗?将子进程stderr重定向到stdout

然而,

$ python >/dev/null -c 'import subprocess;\ 
         subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)' 

输出的东西。为什么会出现这种情况,以及如何在stdout上获取错误消息?

+0

顺便说一句,它是固定在Python 3.5中。 – max 2017-05-26 18:43:10

回答

29

仔细阅读source code给出了答案。

subprocess.STDOUT
特殊值,(...)表示标准误差应进入同一手柄为标准输出:特别是,当它说,documentation是误导。

由于标准输出被设定为“默认”(-1,技术上)时stderr=subprocess.STDOUT进行评价时,标准错误被设置为“默认”的可能。不幸的是,这意味着stderr的输出仍然是stderr。

为了解决这个问题,通过在标准输出文件,而不是subprocess.STDOUT

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.buffer)' 

或者,与Python的传统2.X版本的兼容性:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"], 
         stderr=sys.stdout.fileno())' 
+0

也可以将stderr保持原样:'stderr = sys.stderr.fileno()'。很好的例子;我将在我的所有脚本中简单地使用这种技术。我们有传统的Python 2.x;因此我会确切地知道我告诉它在什么地方没有混淆。 – 2015-09-01 13:52:59

6

其实用subprocess.STDOUT完全是文档中陈述了什么:它将stderr重定向到标准输出,以便例如

proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
output = "" 
while (True): 
    # Read line from stdout, break if EOF reached, append line to output 
    line = proc.stdout.readline() 
    line = line.decode() 
    if (line == ""): break 
    output += line 

结果输出包含stdout和stderr的输出。

stderr=subprocess.STDOUT重定向所有stderr输出直接 stdout调用进程,这是一个主要的区别。

+0

-1这种情况与'stdout'是'None'的问题无关。和'subprocess.STDOUT'不会重定向到“调用控制台”(我认为你的意思是当前进程给出的文件句柄1),如你自己的例子所示 - 如果你用'['ls','/404']',[不显示错误信息](http://ideone.com/2JhcRT)。 – phihag 2013-05-13 07:27:34

+0

你有些不对。不过,我认为这根本不相关,因为这是为了澄清您的文章是否有误导性的文档 - 事实并非如此。我会在你的帖子下面留言,但一年前我没有被允许这么做。 – Maxxim 2014-07-10 11:06:30

+0

'python -c'import subprocess,sys; subprocess.call([“ls”,“/ 404”],stderr = subprocess.STDOUT)'2>/dev/null'表示'ls'的stderr转到stderr(文件描述符2),因为你不会看到任何输出(假设你的系统上没有'/ 404')。 Python文档真的在这个话题上引起了轰动,这对我们shell脚本编写者来说尤其恼人,他们习惯于以各种方式操纵stdout/stderr,并且必须到这里来找出如何做一些应该很简单的事情非混淆。 – 2015-09-01 13:31:04

相关问题