一個困擾我兩年的 Flask bug

優質文章,第一時間送達!

一个困扰我两年的 Flask bug

出處:greyli.com

嚴格來說算不上 bug,而是一個很容易導致出錯的設計。

具體行為是,如果你安裝了 python-dotenv,同時在 Flask 程序的上層目錄創建了 .env 或 .flaskenv 文件,那麼你將沒法成功執行 flask run 等命令,因為這會導致 Flask 沒法正確找到對應的 Flask 程序實例。

這個問題從 Flask 開始引入 CLI 機制開始就存在了,困擾了我兩年。18 年偶然在用戶根目錄創建了一個 .env 文件,發現 Flask 程序沒法運行了,當時遇到的各種 bug 太多,沒仔細考慮這兩者之間的關聯。後來經過幾次測試,才確定下來是上層目錄的 .env 和 .flaskenv 文件導致,但是一時找不到原因,就暫時放下了。直到 19 年 11 月,花了幾個小時排查,還是沒找到原因。

中間花了很長時間來追蹤 Windows 特定的 Flask 程序無法啟動的 bug(TypeError: environment can only contain strings),實在是怕了。因為 Flask 的 CLI 涉及太多東西,有時你要鑽進 python-dotenv(#101) 和 Werkzeug(#1320) 才能找到問題的原因。

但是問題不解決的話,你永遠睡不好覺。《Flask Web 開發實戰》第一部分的示例程序都放在了一個程序倉庫,而且都放在了子目錄,這意味著如果讀者錯誤的在倉庫根目錄創建 .env 和 .flaskenv 文件的話,就會導致子目錄下的六個示例程序沒法運行。前後大概收到 6 個相關的讀者反饋,雖然後續在網站上添加了提醒,在重印的書裡介紹創建 .env/.flaskenv 文件的地方追加提醒,但這終究沒有真正解決問題,而且總會有人可以完美的錯過所有提示。

如果每個人都可以在書上標記出錯位置並共享,那麼這一頁應該會有很多紅色小叉號(參考《超級馬里奧製造》,也許未來某個電子書平臺會做出來這個功能 :P)。

前幾天在這個 Issue 的提醒下,又花了兩個小時排查,這次終於找到原因。加上寫 PR(#3560)和 Issue(#3561),前後兩年一共花了 8 個小時,這個問題終於有了著落。沒意外的話,預計會在下一個版本的 Flask 中更新。下面是具體原因。

本來以為這個問題和 python-dotenv 或 Werkzeug 相關,沒想到只是 Flask 本身代碼的問題,我太笨了,這個問題本可以早一點解決。

按照預定的行為,當安裝了 python-dotenv,Flask 會自動加載 .env 和 .flaskenv 裡的環境變量。python-dotenv 在搜索存儲環境變量的文件時,會從當前目錄開始向上搜索,如果找到就返回對應的文件路徑。但是這時 Flask 如果發現 .env 或 .flaskenv 的所在目錄不是當前目錄,就會把當前工作目錄切換到 .env 和 .flaskenv 所在的目錄(相關源碼)。而如果你的程序模塊或程序包不是和 .env/.flaskenv 同級目錄的話,就會導致找不到程序實例。

使用下面的步驟可以重現:

<code>$ git clone https://github.com/greyli/flask-env-test
$ cd flask-env-test
$ pip install -r requirements.txt # or just pip install flask[dotenv]

$ cd hello
$ flask run
/<code>

示例項目的文件結構如下:

<code>- flask-env-test
- .env
- hello
- app.py
/<code>

像示例程序這樣把程序存儲在 app.py 文件中時,運行 flask run 你會看到下面的報錯:

<code>$ flask run
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
Usage: flask run [OPTIONS]

Error: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the current directory.
/<code>

如果你使用 FLASK_APP 指定了程序的導入路徑,那麼錯誤大概會是這樣:

<code>$ flask run
* Serving Flask app "myapp"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
Usage: flask run [OPTIONS]

Error: Could not import "myapp".
/<code>
  • https://github.com/greyli/helloflask/issues/200

  • https://github.com/pallets/flask/issues/3561

  • https://github.com/pallets/flask/pull/3560


一个困扰我两年的 Flask bug
一个困扰我两年的 Flask bug一个困扰我两年的 Flask bug

PyCharm 2020.1 穩定版發佈

一个困扰我两年的 Flask bug

pip install 今年將出現重大變化!

一个困扰我两年的 Flask bug

入坑 Python 後強烈推薦的一套工具庫

一个困扰我两年的 Flask bug

實戰:Flask + Vue 生成漂亮的詞雲

一个困扰我两年的 Flask bug

Github 熱門,程序員想拿高薪建議都看看

回覆下方「關鍵詞」,獲取優質資源


回覆關鍵詞「 pybook03」,立即獲取主頁君與小夥伴一起翻譯的《Think Python 2e》電子版

回覆關鍵詞「入門資料」,立即獲取主頁君整理的 10 本 Python 入門書的電子版

回覆關鍵詞「m」,立即獲取Python精選優質文章合集

回覆關鍵詞「」,將數字替換成 0 及以上數字,有驚喜好禮哦~


一個困擾我兩年的 Flask bug

好文章,我在看❤️


分享到:


相關文章: