Python 忽略subprocess.Popen的输出

Python 忽略subprocess.Popen的输出,python,subprocess,Python,Subprocess,我从Python脚本中调用了一个java程序,它输出了很多我不想要的无用信息。我已尝试将stdout=None添加到Popen函数中: subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None) 但事实也是如此。有什么想法吗?来自: 如果默认设置为None,则不会发生重定向 您需要将stdout设置为subprocess.PIPE,然后调用.communicate(),并忽略捕获的输出 p = subprocess.Popen(['ja

我从Python脚本中调用了一个java程序,它输出了很多我不想要的无用信息。我已尝试将stdout=None添加到Popen函数中:

subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None)
但事实也是如此。有什么想法吗?

来自:

如果默认设置为
None
,则不会发生重定向

您需要将
stdout
设置为
subprocess.PIPE
,然后调用
.communicate()
,并忽略捕获的输出

p = subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE)
p.communicate()
尽管我怀疑使用
subprocess.call()
已远远满足您的需要:

subprocess.call(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE)
从:

stdin、stdout和stderr分别指定执行程序的标准输入、标准输出和标准错误文件句柄。有效值包括PIPE、DEVNULL、现有文件描述符(正整数)、现有文件对象和None

因此:

这仅存在于3.3及更高版本中。但文件上说:

DEVNULL表示将使用特殊文件os.DEVNULL

os.devnull
可以追溯到2.4版本(在
子流程
存在之前)。因此,您可以手动执行相同的操作:

with open(os.devnull, 'w') as devnull:
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull)
请注意,如果您正在做一些不适合于一行的更复杂的事情,则需要在
Popen
对象的整个生命周期中保持
devnull
打开,而不仅仅是其构造。(也就是说,将整个内容放在带有语句的
中。)

重定向到
/dev/null
(POSIX)或
NUL:
(Windows)的优点是,您不会创建不必要的管道,更重要的是,不会遇到子进程写入该管道时阻塞的边缘情况


缺点是,理论上,
子流程
可能在一些
os.devnull
没有的平台上工作。如果您只关心POSIX和Windows上的CPython、PyPy和Jython(大多数人都关心),那么这永远不会是问题。对于其他情况,请在分发代码之前进行测试。

@sjtaheri:感谢您的更正,我自己应用了它。创建和忽略管道通常是可行的,但如果它写得太多,可能会导致子进程阻塞(当然,它可能会在您的系统上工作,并且对您的某个用户失败),因此,我认为在这里只
打电话而不是
交流
是不安全的。这就是为什么添加了
DEVNULL
,这样您就可以
调用
,而不用担心它。(好吧,它是为稍微复杂一点的情况而存在的,在这里你设置了
stderr=DEVNULL
,但没有设置
stdout
,只是
检查输出
。但想法是一样的。)@abarnert:Ah,不知道添加了这个;刚刚在Python 3文档中找到它。@abarnert:不确定我是否理解清楚。在我看来,‘p.communicate()’只需丢弃stdout管道,它仍然可以快速填充,并导致子进程挂起,如果子进程生成大量输出,则永远不会退出。正确的方法是将标准管道重定向到devnull。对吗?+1:代表德夫努尔。确保
devnull
在子流程处于活动状态时保持打开状态(with语句表示其他情况)。最后一段似乎没有必要:DEVNULL是通过CPython中的os.DEVNULL实现的。os.devnull与Jython一起工作。@J.F.Sebastian:在
检查调用
(位于带有
中)之后,不再需要
devnull
。但是,是的,也许我应该澄清一下,对于不适合一行的更复杂的用例,整个事情需要在
中,而不仅仅是
Popen
@J.F.Sebastian:同时,对于
os.devnull
,它实际上保证存在于
子流程
所在的每个平台上,所以不需要“使用前检查”,或者您只知道Jython上也有它,因此我应该将Jython移动到您不需要检查的平台列表中?在
check\u call()
之后,子进程不活动,因此关于
devnull
的点是静音的(OP使用Popen)。你知道有哪个平台可以使用子流程模块,但os.devnull不知道吗?@J.F.Sebastian:在第一部分,我不确定你现在的观点是什么;你似乎在重复我在回复你第一次评论时说的同样的话。你是同意我的观点,还是我遗漏了什么?在第二部分,我不知道有任何这样的平台,但我不确定是否有这样的平台,因此我认为“分发前检查”是一个很好的建议(在回答中我给出了“理论上……实践中……”的条件,因为大多数人没有什么可检查的)。
with open(os.devnull, 'w') as devnull:
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull)