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

使用SIGTERM信号优雅终止程序时数据库断开连接失败的问题求助

SIGTERM信号优雅终止程序时数据库断开连接失败的问题求助

我最近在学习使用信号机制,写了一个连接数据库并查询打印结果的小Demo。程序里我特意让数据库连接保持打开状态,发送SIGTERM信号确实能终止程序,但当我尝试在信号处理函数里添加数据库断开的逻辑时却失败了。我明明已经把db声明为全局变量了,想请教一下各位我哪里操作错了?我的最终目标是实现程序的优雅关闭,清理数据库连接、Socket连接这类资源。

我的代码如下:

import signal
import sys
from time import sleep

global db
def term_handler(signum,frame):
    print('In term handler')
    db.disconnect()
    #more clean up to come.
    sys.exit()

def main():
   db = connection  # 这里的connection是数据库连接对象,比如pymysql.connect之类的实例
   results = db.select('query here')
   print(results.fetchall())
   #db.disconnect()
   # 上面这行在main里调用是正常的,但放到term_handler里就失败

   signal.signal(signal.SIGTERM,term_handler)

   while True:
       print('yes')
       sleep(2)
   return None
if __name__ == "__main__":
  main()

问题分析

核心问题出在全局变量的作用域处理上:
你虽然在term_handler外部声明了global db,但在main函数里直接赋值db = connection时,Python会把这个db当成main函数的局部变量,并没有把值同步到你之前声明的全局db上。当SIGTERM信号触发term_handler时,全局的db其实是未初始化的状态,这时候调用db.disconnect()自然会抛出类似NameError或者属性不存在的错误。

解决方案

最简单的修正方式是在main函数里也明确声明使用全局的db,这样赋值时才会修改全局变量,而不是创建局部变量:

def main():
    global db  # 声明这里使用全局的db变量
    db = connection
    results = db.select('query here')
    print(results.fetchall())

    signal.signal(signal.SIGTERM,term_handler)

    while True:
        print('yes')
        sleep(2)

额外提示

  1. 信号处理函数里尽量避免执行复杂的IO操作或者调用非信号安全的库函数,不过数据库的disconnect一般是安全的,但最好提前测试确认。
  2. 如果不想用全局变量,也可以考虑用类来封装所有需要清理的资源(比如数据库连接、Socket),然后在信号处理函数里调用类的清理方法,这样代码结构会更清晰。

备注:内容来源于stack exchange,提问作者newdeveloper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:49