https://blog.zengrong.net/post/2632.html
The Werkzeug reloader spawns a child process so that it can restart that process each time your code changes. Werkzeug is the library that supplies Flask with the development server when you call `app.run()`.
See the [`restart_with_reloader()` function code](https://github.com/mitsuhiko/werkzeug/blob/49ee2786630a0307631f4184c3c58d56996cb2b4/werkzeug/_reloader.py#L90-L110); your script is run *again* with `subprocess.call()`.
If you set `use_reloader` to `False` you'll see the behaviour go away, but then you also lose the reloading functionality:
~~~
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)
~~~
You can look for the `WERKZEUG_RUN_MAIN` environment variable if you wanted to detect when you are in the reloading child process:
~~~
if __name__ == '__main__':
import os
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
print '################### Restarting @ {} ###################'.format(
datetime.utcnow())
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0')
~~~
However, if you need to set up module globals, then you should instead use the [`@app.before_first_request` decorator](http://flask.pocoo.org/docs/0.10/api/#flask.Flask.before_first_request) on a function and have that function set up such globals. It'll be called just once after every reload when the first request comes in:
~~~
@app.before_first_request
def before_first_request():
print '########### Restarted, first request @ {} ############'.format(
datetime.utcnow())
~~~
Do take into account that if you run this in a full-scale WSGI server that uses forking or new subprocesses to handle requests, that `before_first_request` handlers *may* be invoked for each new subprocess.
* * * * *
Flask 在 Debug 模式下启动的时候,会被初始化两次。看下面的代码:
> from app import app
> import time
> if __name__ == '__main__':
> print(time.time())
> app.run(port=5000, debug=True)
输出: >
> 1492742262.002537
> * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
> * Restarting with stat
> 1492742262.598912
> * Debugger is active!
> * Debugger pin code: xxx-xxx-xxx
这将导致我们的某些需要在初始化时执行的方法被执行2次,这显然不是我们需要的结果。
出现这样的问题的原因是在开启 Debug 模式的时候,Werkzeug 默认会 [启动一个额外的进程](https://github.com/pallets/werkzeug/blob/0.12.1/werkzeug/_reloader.py#L105-L126) 来监控文件变化以方便重启进程。
要解决这个启动两次的问题,有这样几种方法:
## [](https://blog.zengrong.net/post/2632.html#1-取消自动重启 "1\. 取消自动重启")1\. 取消自动重启
在 Debug 模式下,为了方便调试,Flask 提供了当文件变化的时候自动重启实例的功能。关闭这个功能就可以避免初始化2次的情况。
> app.run(port=5000, debug=True, use_reloader=False)
## [](https://blog.zengrong.net/post/2632.html#2-判断-Werkzeug-主进程是否执行 "2\. 判断 Werkzeug 主进程是否执行")2\. 判断 Werkzeug 主进程是否执行
在 [restart_with_reloader function](https://github.com/pallets/werkzeug/blob/0.12.1/werkzeug/_reloader.py#L105-L126) 中,我们可以看到在新进程启动前,环境变量 `WEAKZEUG_RUN_MAIN`被置为 `'true'` :
> new_environ['WERKZEUG_RUN_MAIN'] = 'true'
通过判断这个变量的值,我们就能保证在启动时仅执行一次:
> if __name__ == '__main__':
> import os
> if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
> print(time.time())
> app.run(port=5000, debug=config.DEBUG)
## [](https://blog.zengrong.net/post/2632.html#3-在第一次请求的时候执行 "3\. 在第一次请求的时候执行")3\. 在第一次请求的时候执行
使用 `before_first_request` 这个钩子,把执行放在 Flask 第一次收到请求的时候。这就避免了2次初始化的干扰。
> @app.before_first_request
> def initialize():
> print(time.time())
## [](https://blog.zengrong.net/post/2632.html#4-在需要请求的时候执行 "4\. 在需要请求的时候执行")4\. 在需要请求的时候执行
和“在第一次请求的时候执行”类似,使用一个开关变量,控制执行仅一次。把执行延迟到了应用逻辑层面。
(全文完)
**参考:**
* [Why does running the Flask dev server run itself twice?](http://stackoverflow.com/a/25504196/1542345)
* [How to stop Flask from initialising twice in Debug Mode?](http://stackoverflow.com/a/9476701/1542345)
- 空白目录
- serial
- serial 整理
- hex to str
- Python3 字符编码
- 字符串编码与Python 3编码
- python3中bytes和string之间的互相转换
- Python3 字符编码
- python整数、字符串、字节串相互转换
- python整数、字符串、字节串相互转换
- python常用的十进制、16进制、字符串、字节串之间的转换(长期更新帖)
- python中pyserial模块使用方法
- 谈谈 Python 程序的运行原理
- flask
- Flask 在 Debug 模式下初始化2次
- Flask中向前端传递或者接收Json文件的方法
- 使用 Python 和 Flask 设计 RESTful API
- 使用 Flask-RESTful 设计 RESTful API