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