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

如何让Python程序遇未捕获异常即退出或通过systemctl异常重启服务?

临时解决方案:让Python服务遇未捕获异常即退出,或通过systemctl强制重启

一、Python层面:强制未捕获异常触发进程退出

默认情况下,线程或异步任务中的未捕获异常不会终止主进程,你可以通过设置全局异常钩子,让任何未处理的异常直接强制退出进程,这样Restart=always就能生效。

1. 处理线程中的未捕获异常

将以下代码添加到服务启动入口:

import sys
import os
import threading

def handle_uncaught_exception(exc_type, exc_value, exc_traceback):
    print(f"未捕获异常: {exc_type.__name__}: {exc_value}", file=sys.stderr)
    # 用os._exit强制终止整个进程,不会被线程阻塞
    os._exit(1)

# 覆盖全局异常钩子
sys.excepthook = handle_uncaught_exception

# 覆盖线程异常钩子(默认线程异常不会触发全局钩子)
def thread_exception_handler(args):
    handle_uncaught_exception(args.exc_type, args.exc_value, args.exc_traceback)

threading.excepthook = thread_exception_handler

2. 处理异步任务中的未捕获异常

如果使用asyncio,可以给所有异步任务加一个包装器,捕获异常后强制退出:

import asyncio

async def async_task_wrapper(coro):
    try:
        await coro
    except Exception as e:
        print(f"异步任务异常: {type(e).__name__}: {e}", file=sys.stderr)
        os._exit(1)

# 启动异步任务时使用该包装器,示例:
# asyncio.run(async_task_wrapper(your_async_function()))

二、Systemd层面:用Watchdog监控服务状态

如果不想修改Python代码,可以通过systemd的Watchdog功能,让系统定期检查服务运行状态,一旦心跳中断就重启服务。

1. 修改systemd服务文件

在你的.service文件中添加以下配置:

[Service]
# 开启Watchdog,设置30秒超时
WatchdogSec=30s
# 服务故障(含Watchdog超时)时重启
Restart=on-failure
# 可选:若服务支持notify机制,设置类型
Type=notify

2. 在Python服务中添加心跳发送逻辑

先安装sdnotify库(pip install sdnotify),然后在服务启动后定期发送心跳:

import sdnotify
import time
import threading

# 初始化systemd通知器
notifier = sdnotify.SystemdNotifier()
# 告知systemd服务已就绪
notifier.notify("READY=1")

# 启动心跳线程,每隔25秒发送一次(需小于WatchdogSec的值)
def send_watchdog_heartbeat():
    while True:
        notifier.notify("WATCHDOG=1")
        time.sleep(25)

# 守护线程,随主进程退出而终止
threading.Thread(target=send_watchdog_heartbeat, daemon=True).start()

若服务因异常卡住无法发送心跳,systemd会在30秒后自动重启服务。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:35:01