You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何子进程关闭stdout句柄后仍能写入?——subprocess代码疑问

Why Closing p1.stdout Doesn’t Break p1’s Output

Great question—this is one of those tricky Unix pipe details that confuses even experienced developers at first. Let’s break down exactly what’s happening here.

First, let’s recap the code we’re looking at:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

What stdout=PIPE Actually Does

When you create p1 with stdout=PIPE, the subprocess module sets up a Unix pipe behind the scenes. Here’s the breakdown:

  • The pipe has two ends: a write end and a read end.
  • p1 (the dmesg process) has its standard output connected to the pipe’s write end. It writes all its output here.
  • Your Python parent process gets a file handle (p1.stdout) pointing to the pipe’s read end. This is how your script would normally read p1’s output directly.

Why Closing p1.stdout Doesn’t Stop p1

The key thing to remember is: each process has its own independent set of file descriptors. The p1.stdout handle in your Python script belongs to your parent process, not to the dmesg child process.

When you call p1.stdout.close(), you’re only closing the parent process’s reference to the pipe’s read end. The dmesg process still has its write end open, and p2 (the grep process) still has its own reference to the pipe’s read end (since we passed stdin=p1.stdout to it).

So dmesg can keep writing to the pipe, and grep can keep reading from it—your parent process just isn’t holding onto that read end anymore.

The Real Reason for p1.stdout.close()

That comment about allowing p1 to receive a SIGPIPE is the crucial part. Here’s why that matters:

  • Unix pipes send a SIGPIPE signal to a process trying to write to a pipe when all read ends of the pipe are closed.
  • If you didn’t close p1.stdout in the parent process, then even if p2 (grep) crashes or exits early, your parent process would still be holding onto the pipe’s read end. That means the pipe isn’t fully closed, so p1 would never get the SIGPIPE signal—it would just hang forever, waiting for someone to read its output.
  • By closing p1.stdout, you ensure that the only read end of the pipe is the one held by p2. If p2 exits, all read ends are gone, and p1 gets a SIGPIPE (which by default terminates the process cleanly) instead of hanging.

Your Experiment Makes Sense Now

When you tested this, you probably saw p1 keep running and outputting to p2—that’s exactly what should happen! The only time closing p1.stdout affects p1 is if p2 dies first. In normal operation (where p2 runs to completion), p1 writes all its output to the pipe, p2 reads it, and everything works as expected.

内容的提问来源于stack exchange,提问作者Aran-Fey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:59:33