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

Python 2中自定义信号处理器存在时读取sys.stdin的异常阻塞行为

分析Python脚本odd-read-blocking.py的信号与输入行为

先来看这个脚本的完整代码:

#!/usr/bin/python
import signal
import sys

sig = None
def handler(signum, frame):
    global sig
    sig = signum

signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)

x = sys.stdin.read(3)
print 'signal', sig
print 'read bytes', len(x)
exit(0)

正常运行的场景

当我们用echo a | ./odd-read-blocking.py传入两个字节(a加换行符)时,因为echo输出后会直接关闭标准输入,sys.stdin.read(3)会读取到所有可用的2个字节后返回,脚本输出如下:

signal None
read bytes 2

这完全符合预期——没有收到任何信号,且读取了所有输入内容。

信号中断阻塞读取的场景

如果我们不用echo,而是直接运行脚本后手动输入a加回车(同样是两个字节),此时sys.stdin.read(3)会进入阻塞状态:因为还没凑够要求的3个字节,且标准输入没有被关闭。这时候如果我们发送SIGINT(比如按下Ctrl+C),会发生什么?

这里要划个重点:Python的默认行为中,被信号中断的read系统调用会抛出IOError,但因为我们自定义了信号处理函数,逻辑就变了——信号处理函数只会把sig变量设为对应的信号编号(比如SIGINT对应2),处理完成后,程序会回到原来的阻塞read调用,继续等待输入,直到输入流关闭或者凑够3个字节。

举个实际测试的例子:

  1. 运行./odd-read-blocking.py
  2. 输入a加回车
  3. 按下Ctrl+C发送信号
  4. 按下Ctrl+D关闭标准输入

此时脚本会输出:

signal 2
read bytes 2

如果希望信号触发后立即终止read操作,可以修改信号处理函数,主动抛出异常或者直接退出程序,比如:

def handler(signum, frame):
    global sig
    sig = signum
    sys.exit(1)  # 直接终止程序

这样收到信号后,脚本会立刻停止阻塞读取,输出捕获到的信号和已读取的字节数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:44:56