我有一个不断运行的应用程序(从Linux开始使用screen -S myapp python3 app.py
,然后将其分离)。它可能是Bottle应用程序,Flask应用程序或任何其他涉及永久运行的事件循环的系统:
import anyframework # can be bottle, flask or anything else
import sqlite3
@route('/')
def index():
c = db.cursor()
c.execute('INSERT INTO test VALUES (?)', ('test',))
c.close() # we can't commit here for *each* client request, it would eat 100ms for each request
return 'hello'
@route('/makeitcrash')
def index():
sdlfksdfs # this will generate an error
def cleanup():
db.commit()
db = sqlite3.connect('test.db')
run()
如何在服务器终止的所有可能情况下可靠地确保
cleanup()
(以及数据库提交)被调用? ,即:screen
内)执行CTRL + C)?
我本打算使用
atexit
并在各处添加try: except:
,但我认为它将引入许多代码重复,以便为每条路线插入try: except:
。这个问题的一般解决方案是什么?
最佳答案
一种方法是捕获信号并在收到信号时进行清理。
import signal
import sys
from bottle import run
def handle_signal(signum, frame):
print(f'handling signal {signum}')
# do cleanup
sys.exit(0)
signal.signal(signal.SIGINT, handle_signal)
# also SIGTERM, et al.
run()
注意事项
正如@MarkAllen指出的,
SIGKILL
永远不会被捕获。我也建议不要一开始就这样处理问题。相反,请查看是否可以设计Web应用程序,以便在关机时无需进行任何清理。 (例如,对每个请求执行持久写入,而不是在内存中进行缓冲。)减少所保持的状态量将有助于简化许多事情,包括如何处理崩溃/关机。
关于python - 如果服务器被CTRL + C杀死或中断或崩溃,请采取措施,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61609523/