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

如何让主进程捕获Ctrl-C?解决os.system()屏蔽KeyboardInterrupt问题

解决主进程捕获KeyboardInterrupt而非子进程的问题

问题原因

os.system()本质是调用系统shell执行命令,执行期间主进程会处于等待状态。当按下Ctrl-C产生SIGINT信号时,信号会被shell转发给它启动的子进程(也就是你调用的python3脚本),同时shell会自行处理该信号,不会将其传递给主进程,因此主进程无法触发KeyboardInterrupt。

解决方案:用subprocess替代os.system

subprocess模块提供了更精细的进程控制能力,能让主进程正常接收信号。下面分两种场景给出实现:

场景1:无需shell(推荐)

直接拆分命令为列表,用subprocess的参数处理输入输出重定向,避免依赖shell,同时更安全:

import subprocess
import sys

# 拆分命令为列表,避免shell解析
cmd = [sys.executable, sys.argv[1]]

# 处理输入输出重定向
with open(sys.argv[2], 'r') as stdin_f, open('measure-temp-output', 'w') as stdout_f:
    try:
        # 等待子进程完成
        subprocess.run(cmd, stdin=stdin_f, stdout=stdout_f, check=True)
    except KeyboardInterrupt:
        print("主进程捕获到Ctrl-C,执行中断处理逻辑")
        # 可根据需求添加子进程终止逻辑(若用Popen可直接调用terminate)

场景2:必须使用shell

如果你的命令依赖shell特性(比如复杂管道),可以开启shell=True,同时设置start_new_session=True让子进程处于新的会话组,这样SIGINT信号只会发送给主进程所在的组:

import subprocess
import sys

cmd = f"{sys.executable} {sys.argv[1]} < {sys.argv[2]} > measure-temp-output"

try:
    # 启动子进程并设置新会话组
    proc = subprocess.Popen(cmd, shell=True, start_new_session=True)
    proc.wait()
except KeyboardInterrupt:
    print("主进程捕获到Ctrl-C")
    # 终止子进程并等待其退出
    proc.terminate()
    proc.wait()

原理说明

  • 用subprocess.run()或Popen()时,主进程并非像os.system()那样完全挂起,而是在等待子进程期间仍能接收信号。
  • 当start_new_session=True时,子进程会创建新的会话组,Ctrl-C触发的SIGINT只会发送给主进程所在的会话组,确保主进程能捕获KeyboardInterrupt。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 09:01:06