
# 環境
為了正確地跑起來,你的應用需要依賴許多不同的軟件。
就算是再怎么否認這一點的人,也無法否認至少需要依賴Flask本身。
你的應用的**運行環境**,在當你想要讓它跑起來時,是至關重要的。
幸運的是,我們有許多工具可以減低管理環境的復雜度。
## 使用virtualenv來管理環境
[virtualenv](http://www.virtualenv.org/en/latest/)是一個能把你的應用隔離在一個**虛擬環境**中的工具。
一個虛擬環境是一個包含了你的應用依賴的軟件的文件夾。一個虛擬環境同時也封存了你在開發時的環境變量。
與其把依賴包,比如Flask,下載到你的系統包管理文件夾,或用戶包管理文件夾,我們可以把它下載到對應當前應用的一個隔離的文件夾之下。
這使得你可以指定一個特定的Python二進制版本,取決于當前開發的項目。
virtualenv也可以讓你給不同的項目指定同樣的依賴包的不同版本。
當你在一個老舊的包含眾多不同項目的平臺上開發時,這種靈活性十分重要。
用了virtualenv,你將只會把少數幾個Python模塊安裝到系統的全局空間中。其中一個會是virtualenv本身:
```sh
# 使用pip安裝virtualenv
$ pip install virtualenv
```
安裝完virtualenv,就可以開始創建虛擬環境。切換到你的項目文件夾,運行`virtualenv`命令。這個命令接受一個參數,作為虛擬環境的名字(同樣也是它的位置,在當前文件夾`ls`下你就知道了)。
```sh
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip...done.
```
這將創建一個包含所有依賴的文件夾。
一旦新的virtual environment已經準備就緒,你需要給對應的virtual environment下的`bin/activate`腳本執行`source`,來激活它。
```
$ source venv/bin/activate
```
你可以通過運行`which python`看到:“python”現在指向的是virtual environment中的二進制版本。
```sh
$ which python
/usr/local/bin/python
$ source venv/bin/activate
(venv)$ which python
/Users/robert/Code/myapp/venv/bin/python
```
當一個virtual environment被激活了,依賴包會被pip安裝到virtual environment中而不是全局系統環境。
你也許注意到了,你的shell提示符發生了改變。
virtualenv在它前面添加了當前被激活的virtual environment,所以你能意識到你并不存在于全局系統環境中。
運行`deactivate`命令,你就能離開你的virtual environment。
```
(venv)$ deactivate
$
```
## 使用virtualenvwrapper管理你的virtual environment
我想要讓你了解到[virtualenvwrapper](http://virtualenvwrapper.readthedocs.org/en/latest/)對于前面的工作做了什么改進,這樣你就知道為什么你應該使用它。
虛擬環境文件夾現在已經位于你的項目文件夾之下。
但是你僅僅是在激活了虛擬環境后才會跟它交互。它甚至不應該被放入版本控制中。所以它呆在項目文件夾中也是挺礙眼的。
解決這個問題的一個方法就是使用virtualenvwrapper。這個包把你所有的virtual environment整理到單獨的文件夾下,通常是`~/.virtualenvs/`。
要安裝virtualenvwrapper,遵循這個[文檔](http://virtualenvwrapper.readthedocs.org/en/latest/)中的步驟。
> **注意**
> 確保你在安裝virtualenvwrapper時不在任何一個virtual environment中。你需要把它安裝在全局空間,而不是一個已存在的virtual environment中
現在,你不再需要運行`virtualenv`來創建一個環境,只需運行`mkvirtualenv`:
```sh
$ mkvirtualenv rocket
New python executable in rocket/bin/python
Installing setuptools, pip...done.
```
在你的virtual environment目錄之下,比如在`~/.virtualenv`之下,`mkvirtualenv`創建了一個文件夾,并替你激活了它。
就像普通的`virtualenv`,`python`和`pip`現在指向的是virtual environment而不是全局系統。
為了激活想要的環境,運行這個命令:`workon [environment name]`,而`deactivate`依然會關閉環境。
## 記錄依賴變動
隨著項目增長,你會發現它的依賴列表也一并隨著增長。在你能運行一個Flask應用之前,即使已經需要數以十記的依賴包也毫不奇怪。
管理依賴的最簡單的方法就是使用一個簡單的文本文件。
pip可以生成一個文本文件,列出所有已經安裝的包。它也可以解析這個文件,并在新的系統(或者新的環境)下安裝每一個包。
### pip freeze
**requirements.txt**是一個常常被許多Flask應用用于列出它所依賴的包的文本文件。它是通過`pip freeze > requirements.txt`生成的。
使用`pip install -r requirements.txt`,你就能安裝所有的包。
> **注意**
> 在freeze或install依賴包時,確保你正為于正確的virtual environment之中。
### 手動記錄依賴變動
隨著項目增長,你可能會發現`pip freeze`中列出的每一個包并不再是運行應用所必須的了。
也許有些包只是在開發時用得上。`pip freeze`沒有判斷力;它只是列出了當前安裝的所有的包。所以你只能手動記錄依賴的變動了。
你可以把運行應用所需的包和開發應用所需的包分別放入對應的*require_run.txt*和*require_dev.txt*。
## 版本控制
選擇一個版本控制系統并使用它。
我推薦Git。如我所知,Git是當下最大眾的版本控制系統。
在刪除代碼的時候無需擔憂潛在的巨大災難是無價的。
你現在可以對過去那種把不要的代碼注釋掉的行為說拜拜了,因為你可以直接刪掉它們,即使將來突然需要,也可以通過`git revert`來恢復。
另外,你將會有整個項目的備份,存在Github,Bitbucket或你自己的Git server。
### 什么不應該在版本控制里
我通常不把一個文件放在版本控制里,如果它滿足以下兩個原因中的一個。
1. 它是不必要的
2. 它是不公開的。
編譯的產物,比如`.pyc`,和virtual environment(如果你因為某些原因沒有使用virtualenvwrapper)正是前者的例子。
它們不需要加入到版本控制中,因為它們可以通過`.py`或`requirements.txt`生成出來。
接口密鑰(調用接口時必須傳入的參數),應用密鑰,以及數據庫證書則是后者的例子。
它們不應該在版本控制中,因為一旦泄密,將造成嚴重的安全隱患。
> **注意**
> 在做安全相關的決定時,我會假設穩定版本庫將會在一定程度上被公開。這意味著要清除所有的隱私,并且永不假設一個安全漏洞不會被發現,
> 因為“誰能想到他們會干出什么事情?”
在使用Git時,你可以在版本庫中創建一個特別的文件名為*.gitignore*。
在里面,能使用正則表達式來列出對應的文件。任何匹配的文件將被Git所忽略。
我建議你至少在其中加入`*.pyc`和`/instance`。instance文件夾中存放著跟你的應用相關的不便公開的配置。
```
.gitignore:
*.pyc
instance/
```
> **參見**
> * 在這里你可以了解什么是*.gitignore* : http://git-scm.com/docs/gitignore
> * Flask文檔中對instance目錄的一段介紹 : http://flask.pocoo.org/docs/config/#instance-folders
## 調試
### 調試模式
Flask有一個便利的特性叫做“debug mode”。在你的應用配置中設置`debug = True`就能啟動它。
當它被啟動后,服務器會在代碼變動之后重新加載,并且一旦發生錯誤,錯誤會打印成一個帶交互式命令行的調用棧。
> **注意**
> 不要在生產環境中開啟debug mode。交互式命令行運行任意的代碼輸入,如果是在運行中的網站上,這將導致安全上的災難性后果。
> **另見**
> - 閱讀一下quickstart頁面的debug mode部分 : http://docs.jinkan.org/docs/flask/quickstart.html#debug-mode
> - 這里有一些關于錯誤處理,日志記錄和使用其他調試工具的信息 : http://docs.jinkan.org/docs/flask/errorhandling.html
### Flask-DebugToolbar
[Flask-DebugToolbar](http://flask-debugtoolbar.readthedocs.org/en/latest/) 是用來調試你的應用的另一個得力工具。在debug mode中,它在你的應用中添加了一個側邊條。
這個側邊條會給你提供有關SQL查詢,日志,版本,模板,配置和其他有趣的信息。
## 總結
* 使用virtualenv來打包你的應用的依賴包。
* 使用virtualenvwrapper來打包你的virtual environment。
* 使用一個或多個文本文件來記錄依賴變化。
* 使用一個版本控制系統。我推薦Git。
* 使用.gitignore來排除不必要的或不能公開的東西混進版本控制。
* debug mode會在開發時給你有關bug的信息。
* Flaks-DebugToolbar拓展將給你有關bug更多的信息。