当python进程被杀死时运行atexit()

sbdsn5lh  于 2023-05-16  发布在  Python
关注(0)|答案(4)|浏览(177)

我有一个在后台运行的Python进程,我希望它只在脚本终止时生成一些输出。

def handle_exit():
    print('\nAll files saved in ' + directory)
    generate_output()

atexit.register(handle_exit)

调用引发KeyboardInterupt异常,sys.exit()正确调用handle_exit(),但是如果我从终端执行kill {PID},它会终止脚本而不调用handle_exit()。
有没有一种方法可以终止正在后台运行的进程,并且在终止之前仍然运行handle_exit()

3xiyfsfu

3xiyfsfu1#

试试signal.signal.它允许捕获任何系统信号:

import signal

def handle_exit():
    print('\nAll files saved in ' + directory)
    generate_output()

atexit.register(handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)

现在你可以执行kill {pid}handle_exit将被执行。

mwngjboj

mwngjboj2#

要在Windows上调试PyCharm时启用信号:
1.在PyCharm中,点击Ctrl + Shift + A以打开“查找操作...”菜单。
1.搜索“注册表”并按回车键
1.找到键kill.windows.processes.softly并启用它(您可以开始键入“kill”,它将搜索该键)
1.重启PyCharm

7cjasjjr

7cjasjjr3#

要检查您的系统并查看正在调用哪个信号:

import signal
import time

def handle_signal(sig_id, frame):
    sig = {x.value: x for x in signal.valid_signals()}.get(sig_id)
    print(f'{sig.name}, {sig_id=}, {frame=}')
    exit(-1)

for sig in signal.valid_signals():
    print(f'{sig.value}: signal.{sig.name},')
    signal.signal(sig, handle_signal)

time.sleep(30)
x4shl7ld

x4shl7ld4#

如果你想自己处理信号,根据Python文档,handler函数需要两个参数。
如果处理SIGINT信号,则必须在处理函数中调用sys.exit(0);否则,按Ctrl + C时程序不会终止。
正如KamiCuk所提到的,如果atexit注册的函数与信号处理函数相同,则该函数将被调用两次。
因此,我倾向于使用单独的函数来处理信号处理程序和atexit注册。下面是一个例子:

import atexit
import signal
import sys

def on_exit():
    print('real clean code here')

def handle_exit(signum, frame):
    sys.exit(0)

atexit.register(on_exit)
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)

正确处理这些信号可能很棘手,特别是对于跨平台应用程序。
为了解决这个问题,我创建了一个名为safe-exit的包。
文档可以在这里找到:https://safe-exit.readthedocs.io/en/latest/

相关问题