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

Python 3.5及以上版本中如何用Ctrl+C中断recvfrom调用?

嘿,我来帮你搞定UDP服务器按下Ctrl+C无法正常退出的问题!

首先得把事儿说透:从Python 3.4开始,按照PEP 475的规范,像socket.recvfrom()这类阻塞的系统调用在收到SIGINT(就是你按Ctrl+C发送的中断信号)时,会自动重启调用,而不是抛出异常或者返回空数据——这就是为啥你的原代码按Ctrl+C没反应,recvfrom会一直死堵着不撒手。

下面给你两种靠谱的解决方案,随便挑一种用就行:

方案一:捕获信号+Socket超时

这种方法通过捕获中断信号标记退出状态,同时给socket设置超时,让循环有机会检查退出标志:

import socket
import signal

# 定义全局退出标志
should_exit = False

def handle_sigint(signum, frame):
    global should_exit
    print("\n收到Ctrl+C,准备退出服务器...")
    should_exit = True

# 注册SIGINT信号处理函数
signal.signal(signal.SIGINT, handle_sigint)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 5555))
# 设置1秒超时,让recvfrom每隔1秒就跳出阻塞,给循环检查退出标志的机会
s.settimeout(1.0)

while not should_exit:
    try:
        data, addr = s.recvfrom(2048)
        print("received:", data.decode(), "from", addr)
    except socket.timeout:
        # 超时只是用来触发循环检查,不需要额外处理
        continue
    except Exception as e:
        print(f"运行出错:{e}")
        break

print("服务器已正常退出")
s.close()

方案二:用select实现非阻塞监听

另一种思路是用select模块监听socket的可读事件,同时设置超时,既能等待数据又能响应信号:

import socket
import select
import signal

should_exit = False

def handle_sigint(signum, frame):
    global should_exit
    print("\n收到Ctrl+C,准备退出服务器...")
    should_exit = True

signal.signal(signal.SIGINT, handle_sigint)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', 5555))

while not should_exit:
    # 监听socket是否可读,超时1秒
    readable, _, _ = select.select([s], [], [], 1.0)
    if s in readable:
        data, addr = s.recvfrom(2048)
        print("received:", data.decode(), "from", addr)

print("服务器已正常退出")
s.close()

为啥这两种方法能行?

  • 方案一靠socket超时,让recvfrom每隔1秒就抛出超时异常回到循环,这时就能检查should_exit标志——按下Ctrl+C时,信号处理函数会把标志改成True,下一次超时后循环就会正常退出。
  • 方案二用select.select()替代直接调用recvfrom,它会在超时时间内等待socket可读,超时后自动回到循环检查退出标志,同样能及时响应Ctrl+C信号。

这两种方法都能让你的UDP服务器优雅处理Ctrl+C,再也不用依赖原代码里“recvfrom返回空数据”的逻辑啦(毕竟PEP475之后这种情况根本不会发生)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:17:49