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

如何在通过任务计划程序终止代码时仍执行finally块?

问题原因

Windows任务计划终止任务时,默认会发送强制终止指令(类似Unix的SIGKILL),直接终止进程,不会给Python程序执行finally块的机会。而PyCharm/控制台终止时,发送的是正常中断信号(如SIGINT),Python会触发异常处理流程,执行finally代码。

解决方案

1. 捕获Windows控制台关闭事件

通过pywin32库注册控制台关闭事件处理器,在任务计划终止程序时触发自定义清理逻辑。

首先安装依赖:

pip install pywin32

修改代码如下:

import time
from datetime import datetime
import win32api
import win32con

def log_info(message: str):
    with open('somefile.log', 'a') as file:
        file.write(f'{datetime.now()}: {message}\n')

def handle_termination(event):
    # 处理控制台关闭、任务终止、系统注销/关机等事件
    if event in (win32con.CTRL_C_EVENT, win32con.CTRL_CLOSE_EVENT, win32con.CTRL_LOGOFF_EVENT, win32con.CTRL_SHUTDOWN_EVENT):
        log_info('Process ended (terminated by task scheduler)')
        return True  # 告知系统已处理事件

# 注册事件处理器
win32api.SetConsoleCtrlHandler(handle_termination, True)

try:
    log_info('Process started')
    time.sleep(1000)  # 模拟长时间运行
finally:
    # 正常退出时仍会执行
    log_info('Process ended (normal exit)')

2. 封装为Windows服务

将脚本包装成Windows服务,服务的终止会触发标准的stop事件,确保清理逻辑稳定执行。

示例代码(依赖pywin32):

import win32serviceutil
import win32service
import win32event
import time
from datetime import datetime

def log_info(message: str):
    with open('somefile.log', 'a') as file:
        file.write(f'{datetime.now()}: {message}\n')

class MyService(win32serviceutil.ServiceFramework):
    _svc_name_ = "LongRunningPythonService"
    _svc_display_name_ = "Long Running Python Service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.running = True

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.running = False
        log_info('Process ended (service stopped)')

    def SvcDoRun(self):
        log_info('Process started (service running)')
        while self.running:
            time.sleep(10)  # 模拟业务逻辑

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

安装服务(需管理员权限控制台):

python your_script.py install

启动服务:

python your_script.py start

任务计划可配置为启动/停止该服务,终止时会自动触发SvcStop方法执行清理。

3. 调整任务计划终止策略

在任务计划的设置选项卡中,找到“当请求停止任务时”,选择允许任务在请求停止时完成,而非“立即终止任务”。此设置需配合方案1使用,确保程序能响应终止请求并执行清理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:20:15