让flask在出现语法错误时仍然自动重启
1问题描述:
flask自带的reload只能在语法没毛病的情况下auto_relaod,但是如果有语法错误,进程就会报错退出。
这时修改完语法错误,还得在控制台按“↑”和“enter”重新执行一次python3 app.py 重新启动flask。
希望省掉手动重启flask的过程
2解决方案
用flask-failsafe插件。
这样语法错误也会reload,语法错误修正,系统继续运行。这样手和光标不用频繁切到控制台,也省了“↑”和“enter”的按键。懒人专用。
这个插件使用很简单:

myapp模拟flask应用。main.py作为启动脚本。核心就是装饰器,监控各种文件改动。然后reraise。
3原理
(好奇心不强的可以不看)
虽然flask_failsafe是代码只有80行的一个单独py文件,但是还不是太能看懂啊啊……把我理解的作为注释加进去了:
import functools
import sys
import traceback import flask PY2 = sys.version_info[0] == 2 def failsafe(func):
"""
Wraps an app factory to provide a fallback in case of import errors. Takes a factory function to generate a Flask app. If there is an error
creating the app, it will return a dummy app that just returns the Flask
error page for the exception. This works with the Flask code reloader so that if the app fails during
initialization it will still monitor those files for changes and reload
the app.
""" @functools.wraps(func)
def wrapper(*args, **kwargs):
extra_files = [] try:
#如果create_app运行不报错。就直接在开头退出。
return func(*args, **kwargs)
except:
#捕获异常,并打印
exc_type, exc_val, exc_tb = sys.exc_info()
traceback.print_exc()
#添加异常中依赖的文件,和“SyntaxError”爆出来的文件。
tb = exc_tb
while tb:
filename = tb.tb_frame.f_code.co_filename
extra_files.append(filename)
tb = tb.tb_next if isinstance(exc_val, SyntaxError):
extra_files.append(exc_val.filename)
#启动dummy app,专门用来显示错误的文件
app = _FailSafeFlask(extra_files)
app.debug = True @app.route('/')
@app.route('/<path:path>')
def index(path='/'):
reraise(exc_type, exc_val, exc_tb) return app return wrapper if PY2:
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
else:
def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value class _FailSafeFlask(flask.Flask):
"""
Binds the extra_args parameter of run() to include the extra files we want to
monitor for changes.
""" def __init__(self, extra_files):
flask.Flask.__init__(self, __name__)
self.extra_files = extra_files def run(self, *args, **kwargs):
extra_files = self.extra_files
if 'extra_files' in kwargs:
extra_files = extra_files + kwargs['extra_files']
kwargs['extra_files'] = extra_files
flask.Flask.run(self, *args, **kwargs)
关键好像是最后2行 flask自己会跟踪'extra_files'文件的改动。又百度了一下,准确地说是werkzeug用子进程实现的这个功能。后面会简单说到原理。
当extra_files有改动后,dummy_app跟踪改动,flask的auto_loader机制会保证dummy_app先退出,再重启。
关键就是这个重启,为什么能重复执行我们写的create_app,而不是简单重启dummy_app.run()呢?
根据flask的auto_reloader机制的讲解,
当从进程执行到
run_with_reloader时,便进入了条件分支,而不会再无限启新的「从进程」耗光资源。而分支内部可以看到,开了一条线程来跑main_func也就是启动web服务的方法,紧接着启动reloader_loop也就是监视文件改动的循环。
大概是:werkzeug的自动重启机制是:用我们传进去的命令行参数,通过subprocess建立新的python解释器。也就是在新进程执行"python3 main.py"
这也就保证了main.py里我们的create_app()会在文件被修改后执行,这个和flask-failsafe没有关系。
对比一下重启过程:
普通的flask app是这样的:
1文件被改动,werkzeug的子进程会监控到改动,然后报exitcode 3退出
2 werkzeug试图重启subprocess(用我们开始传入的参数python main.py 执行create_app() 和app.run())
3 如果重启中出现语法错误,就会报错非exitcode 3,先退出子进程,再退出主进程;
而文艺的flask-failsafe 1 2是一样的,但之后就不一样了,它要实现“如果create_app失败,不会退出主进程,继续监控出错的文件,出错文件被改动后试图重新运行create_app”:
3 如果重启时在create_app里出现语法错误,捕获异常,根据异常报出来的文件构造extra_files
4 用extra_files参数启动一个dummy_app代替用户本来想创建的app
5 dummy_app.run()正常运行,但其实dummy_app什么都不做,因为这时有文件是错的。
6如果有文件改动了,重复1
这个dummy_app巧妙性在于,充分利用了werkzeug的强大的自动重启机制:
1它会正常启动,正常run。因为它本身并没有import或用到这些出错的extra_files,只是个超级简单的app
2它保留了我们传入的arg和kwarg用于启动subprocess。在这一点上,它的行为和原生的app一样,所以它一旦退出,subprocess重启,会导致重启我们写的create_app,试图创建我们的app, 而不是简单重建自己。
3它会跟踪错误的extra_files的改动而触发werkzeug的重启机制。
所以,如果没有werkzeug基于subprocess,重启新解释器的重启机制,是没法实现重新执行create_app的。
以我的水平,理解到这样就基本满意啦。
让flask在出现语法错误时仍然自动重启的更多相关文章
- Note Pad++ 关闭语法错误时在代码下面的红线标识
菜单栏 —- 插件 —- DSpellCheck . 将勾去掉即可
- 用Supervisor实现进程守护,在异常退出时自动重启
程序启动后,有些是以daemon的形式运行,但在意外退出后,如果不能及时重新启动,会有比较严重的影响. 比如Zimg在图片处理中由于某些图片处理失败,会导致zimg进程挂掉,影响正常的服务提供,并且只 ...
- SQL SERVER 重组含有特殊字符的索引时遇到“关键字 'with' 附近有语法错误.”
案例描述 这是在索引重组过程中遇到的有意思的错误案例,搜索了一下也没有看到相关资料,估计我第一个碰到这类错误的人(It's just a joke).具体情况是YourSQLDba在做维护数据库索引时 ...
- LoadRunner 11安装Micosoft Visual C++ 2005 SP1时提示命令行选项语法错误
如果安装LoadRunner 11时弹窗提示"Micosoft Visual C++ 2005 SP1 可再发行组件包(X86):'命令行选项语法错误.键入命令 / ? 可获得帮助信息'&q ...
- 解决SQL将varchar值转换为数据类型为int的列时发生语法错误
今天遇到一个这样的错误,具体的报错情况如下 解决的方案如下. 数据库MSSQL在比较大小时,出错提示:“将 varchar 值 '24.5' 转换为数据类型为 int 的列时发生语法错!”分析数据库设 ...
- 安装loadrunner时出现”命令行选项语法错误键入命令 \?获得帮助“的解决方法
安装LR11 时,安装Microsoft Visual c++2005 sp1运行时组件,就会提示命令行选项语法错误,键入“命令/?”可获取帮肋信息1.进入loadrunner-11\Addition ...
- notepad++新建文档时,会出现语法错误的红色下波浪线
notepad++新建文档时,会出现语法错误的红色下波浪线: 原因:新建文档时默认设置语言为PHP. 解决方法:修改默认语言为java或JavaScript,如下: 小结:打开文档时,也可能出现下波浪 ...
- Mybatis 的 xml 文件语法错误,启动项目时控制台一直循环解析但是不打印错误
重写SqlSessionFactoryBean的buildSqlSessionFactory方法: eg: package com.slp; import java.io.IOException; i ...
- 关于SubSonic3.0未处理InvalidOperationException异常(关键字TOP附近有语法错误)的处理
早上在测试程序时,使用了Top这个属性,没想到马上抛出了个“未处理InvalidOperationException异常(关键字'TOP'附近有语法错误)”这个错误提示,见下图: 然后Debug一下, ...
随机推荐
- winform dataGridView DataGridViewComboBoxColumn 下拉框事件代码
有一个dataGridView ,有一列是DataGridViewComboBoxColumn .我用动态绑定,在绑定数据的时候.我们也给这一列绑定数据 在dataGridView的RowsAdded ...
- 做报表需要知道的基本的SQL语句
为客户做报表需要操作数据库,基本的SQL是必须要掌握的,下面介绍做报表最常用的SQL语句. 方法/步骤 1 查询数据:编号表示查询顺序. (8) select (9) distinct (11 ...
- 使用TreeView加载XML文件
PS: 由于小弟初学编程,本文只写实现方式,代码写的不是很好请见谅! 1.需要读取的xml文档内容 2. 最终实现效果 3 貌似看起实现起来很复杂 但是想想还是挺简单 思路: 读取XML文档 →获 ...
- redis桌面管理工具 redis-desktop-manager使用指南(转)
版权声明:转自 http://blog.csdn.net/li396864285/article/details/54629898 概要:一款好用的Redis桌面管理工具,支持命令控制台操作, ...
- activemq 消息队列服务器
ActiveMQ 安装配置 更多 安装 前置条件:1)安装JDK:2)配置 JAVA_HOME 环境变量,确保 echo $JAVA_HOME 输出JDK的安装路径 下载:wget http://ww ...
- 数据仓库基础(六)数据的ETL
本文转载自:http://www.cnblogs.com/evencao/p/3140487.html ETL是数据抽取(Extract).转换(Transform).加载(Load)的简写,是构建数 ...
- charles破解
替换安装路径->Charles\lib下的charles.jar文件成破解版jar文件,如果再次启动未弹出30天试用的提示,说明破解成功 charles:https://pan.baidu.co ...
- 01: MySql简介
MySQL其他篇 目录: 参考网站 1.1 数据库介绍 1.2 视图 1.3 触发器 1.4 事物 1.1 数据库介绍返回顶部 1.什么是数据库? 1. 数据库(Database)是按照数据结构来组织 ...
- 20145307陈俊达《网络对抗》Exp9 Web安全基础实践
20145307陈俊达<网络对抗>Exp9 Web安全基础实践 基础问题回答 1.SQL注入攻击原理,如何防御? SQL注入攻击就是通过把SQL命令插入到Web表单递交或输入域名或页面请求 ...
- linux内核分析 第5章读书笔记
第五章 系统调用 一.与内核通信 系统调用在用户控件进程和硬件设备之间添加了一个中间层,作用有: 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进程都运行在虚拟系统中,而在用 ...