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

读取子进程部分标准输出后退出,如何不终止子进程?

问题背景

我有两个脚本A.py和B.py,A启动运行B的子进程,希望A在退出前读取B的几行标准输出(stdout),且A退出后B能继续运行至完成。我编写了一段看似可行的代码:

B.py

import os
import sys
import platform
import time
import subprocess
import tempfile


dirname = "test_dir"
# Putting data into our directory
filename = str(time.time())
with open(os.path.join(dirname, filename), mode="w", encoding="utf8") as f:
  f.write("a file")

kwargs = {}
if platform.system() == "Windows":
  CREATE_NEW_PROCESS_GROUP = 0x00000200
  DETATCHED_PROCESS = 0x00000008
  kwargs.update(creationflags=DETATCHED_PROCESS | CREATE_NEW_PROCESS_GROUP)
else:
  kwargs.update(start_new_session=True)

temp = tempfile.TemporaryFile()
p = subprocess.Popen([sys.executable, "A.py"],
                     stdin=subprocess.DEVNULL, stdout=temp, **kwargs)
time.sleep(2)
temp.seek(0)
data = temp.readline()
line = data.decode("utf-8").rstrip()
print(line)
print("goodbye")
sys.exit(0)

A.py

import time
import socket
import sys
import os

DEFAULT_PORT = 9563

N = 10

try:
  # Building manager lock to prevent another instance from running
  lock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  lock.bind(("localhost", DEFAULT_PORT))
except OSError:
  print("A is already running")
  sys.exit(3)

filename = "log.txt"
dirname = "test_dir"
for i in range(N):
  with open(filename, "a", encoding="utf8") as f:
    num_files = len(os.listdir(dirname))
    f.write(f"idx: {i}, {time.asctime()}, {num_files} files found\n")
    print(f"Still Writing {i}", flush=True)
  time.sleep(1)

我的做法是通过临时文件(tempfile)接收子进程的标准输出,等待一段时间后读取几行输出再关闭文件,子进程似乎能在文件关闭后继续运行。请问:

  1. 这种实现方式是否合理?
  2. B结束后临时文件会如何处理?
  3. 临时文件关闭后子进程的标准输出会怎样?

问题解答

1. 实现方式是否合理?

这种方式不算合理,核心问题如下:

  • 依赖time.sleep(2)硬编码等待时间:子进程启动速度、输出时机存在不确定性,可能出现读不到内容或等待时间冗余的情况,完全不可靠。
  • 跨进程读写无同步机制:父进程读取临时文件时,子进程可能还在写入,容易拿到不完整的输出,甚至引发潜在的IO冲突。
  • 子进程后续输出会因文件关闭出现异常(见第三个问题),无法保证子进程能完整运行。

更可靠的替代方案:

  • 使用命名管道(FIFO):父进程创建管道,子进程输出到管道,父进程读取部分内容后关闭管道,子进程后续输出可重定向到/dev/null或固定日志文件。
  • 让子进程自主管理日志:子进程启动时直接将输出写入固定日志文件,父进程读取该文件的前几行即可,后续子进程不受父进程操作影响。

2. B结束后临时文件会如何处理?

你使用的tempfile.TemporaryFile()创建的临时文件,会在对象被显式关闭或Python解释器回收资源时自动删除:

  • 当B.py执行sys.exit(0)正常退出时,temp对象会被销毁,触发临时文件的自动删除操作。
  • 若B因异常退出且未正常清理temp对象,部分系统下临时文件可能残留,但正常退出场景下不会有残留。

3. 临时文件关闭后子进程的标准输出会怎样?

B退出后临时文件被关闭,子进程的stdout指向已失效的文件描述符,不同系统表现不同:

  • Unix/Linux系统:子进程继续写stdout会触发EPIPE错误,默认会被SIGPIPE信号终止,无法继续运行完成。
  • Windows系统:子进程写已关闭的句柄会返回错误,但不会直接终止,不过后续输出会全部丢失,子进程虽可能继续运行,但输出完全无法被捕获。

这意味着你的测试中看似能运行,只是因为B退出后子进程还没来得及触发报错,实际场景下大概率会导致子进程异常终止或输出丢失,无法达到“子进程继续运行至完成”的目标。


内容的提问来源于stack exchange,提问作者Vincent Hu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:15:02