如何取消通过os.execvp()启动的进程的标准输出(stdout)
解决os.execvp启动进程时重定向stdout到/dev/null的问题
这问题我之前调试代码时也踩过坑,咱们先搞清楚为啥你之前的方法没生效,再给你靠谱的实现方案:
为啥之前的方法行不通?
- 第一种修改
sys.stdout的方式:sys.stdout只是Python层面封装的文件对象,os.execvp会直接替换当前进程的整个内存空间,新启动的进程根本不会继承Python的这个变量,它只会继承原进程的文件描述符(比如fd=1对应stdout),所以改sys.stdout对新进程完全没影响。 - 第二种
os.dup2的方式:逻辑方向是对的,但可能你没处理好文件描述符的关闭,或者操作顺序有问题?不过更规范的写法能确保生效。
正确的实现代码
下面是经过验证的写法,核心是直接修改底层的文件描述符1(对应stdout),让它指向/dev/null:
import os # 替换成你的进程路径和参数 proc_path = "/usr/bin/your-program" proc_args = ["your-program", "--some-arg"] # 打开/dev/null,获取它的文件描述符 devnull_fd = os.open(os.devnull, os.O_WRONLY) try: # 将stdout(文件描述符1)重定向到/dev/null os.dup2(devnull_fd, 1) finally: # 关闭原来的/dev/null文件描述符,避免资源泄漏 os.close(devnull_fd) # 启动目标进程,此时它的stdout会输出到/dev/null os.execvp(proc_path, proc_args)
额外说明
- 为什么要关闭devnull_fd?
os.dup2会把devnull_fd的内容复制到fd=1,之后原来的devnull_fd就没用了,关闭它可以避免文件描述符泄漏——虽然execvp之后原进程会退出,但养成好习惯总是没错的。 - 如果需要同时重定向stderr?
只要把文件描述符2(对应stderr)也用同样的方式重定向到/dev/null就行,在os.dup2(devnull_fd, 1)后面加一行os.dup2(devnull_fd, 2)即可。 - 更简洁的写法(Python 3.4+)
可以用os.open的os.O_CLOEXEC标志,这样在exec的时候会自动关闭这个fd,不用手动close:devnull_fd = os.open(os.devnull, os.O_WRONLY | os.O_CLOEXEC) os.dup2(devnull_fd, 1) os.execvp(proc_path, proc_args)
内容的提问来源于stack exchange,提问作者Y_Z
相关产品推荐
相关产品推荐

