忽略subprocess.Popen的输出

14 投票
2 回答
36859 浏览
提问于 2025-04-17 15:00

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

subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None)

但是效果还是一样。有没有什么好的办法?

2 个回答

7

来自文档的内容:

在默认设置为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)
48

根据3.3版本的文档

stdin、stdout和stderr分别代表程序的标准输入、标准输出和标准错误输出。有效的值有PIPE、DEVNULL、一个已经存在的文件描述符(正整数)、一个已经存在的文件对象,以及None。

所以:

subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=subprocess.DEVNULL)

这个功能只在3.3版本及之后的版本中存在。但文档中提到:

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

os.devnull早在2.4版本就已经存在了(在subprocess出现之前)。所以,你可以手动实现同样的功能:

with open(os.devnull, 'w') as devnull:
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull)

注意,如果你要做的事情比较复杂,不能只用一行代码来完成,你需要在整个Popen对象的生命周期内保持devnull处于打开状态,而不仅仅是在创建的时候。(也就是说,把整个过程放在with语句里。)

将输出重定向到/dev/null(在POSIX系统上)或NUL:(在Windows上)的好处是,你不会创建一个不必要的管道,更重要的是,避免了子进程在写入这个管道时可能出现的阻塞情况。

缺点是,从理论上讲,subprocess可能在某些平台上工作,而os.devnull则不适用。如果你只关心在POSIX和Windows上的CPython、PyPy和Jython(这对大多数人来说都是这样),那么这不会成为问题。对于其他情况,发布代码之前最好先测试一下。

撰写回答