第十四章:应用构建模块-atexit:程序关闭回调-什么情况下不调用atexit函数

14.10.4 什么情况下不调用atexit函数
如果满足以下任意一个条件,就不会调用为atexit注册的回调。
1.程序由于一个信号而终止。
2.直接调用了os._exit()。
3.检测到解释器中的一个致命错误。
可以更新subprocess一节中的例子,显示程序因为一个信号而终止时会发生什么。这里涉及两个文件,父程序和子程序。父程序启动子程序,暂停,然后中止子程序。

import os
import signal
import subprocess
import time

proc = subprocess.Popen('./atexit_signal_child.py',shell=True)
print('PARENT: Pausing before sending signal...')
time.sleep(1)
print('PARENT: Signaling child')
os.kill(proc.pid,signal.SIGTERM)

子程序建立一个atexit回调,然后休眠,直至信号到来。

import atexit
import time
import sys

def not_called():
    print('CHILD: atexit handler should not have been called')

print('CHILD: Registering atexit handler')
sys.stdout.flush()
atexit.register(not_called)

print('CHILD: Pausing to wait for signal')
sys.stdout.flush()
time.sleep(5)

运行这个脚本时,会生成以下输出。

子程序不会打印嵌在not_called()中的消息。
通过使用os._exit(),程序就可以避免调用atexit回调。

import atexit
import os

def not_called():
    print('This should not be called')

print('Registering')
atexit.register(not_called)
print('Registered')

print('Exiting...')
os._exit(0)

由于这个例子绕过了正常的退出路径,所以没有运行回调。另外,打印输出不会刷新,所以要提供-u选项运行这个示例来启用无缓冲的I/O。
在这里插入图片描述
为了确保运行回调,可以在要执行的语句外运行或者通过调用sys.exit()使程序中止。

import atexit
import sys

def all_done():
    print('all_done()')

print('Registering')
atexit.register(all_done)
print('Registered')

print('Exiting...')
sys.exit()

这个例子调用了sys.exit(),所以会调用注册的回调。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43193719/article/details/94650590