12. 虛擬環境與套件
******************


12.1. 簡介
==========

Python 應用程式通常會用到不在標準函式庫的套件和模組。應用程式有時候會
需要某個特定版本的函式庫，因為這個應用程式可能需要某個特殊的臭蟲修正，
或是這個應用程式是根據該函式庫特定版本的介面所撰寫。

這意味著不太可能安裝一套 Python 就可以滿足所有應用程式的要求。如果應用
程式 A 需要一個特定的模組的 1.0 版，但另外一個應用程式 B 需要 2.0 版，
那麼這整個需求不管安裝 1.0 或是 2.0 都會衝突，以致於應用程式無法使用。

解決方案是創建一個*虛擬環境（virtual environment）*，這是一個獨立的資
料夾，並且裡面裝好了特定版本的 Python，以及一系列相關的套件。

不同的應用程式可以使用不同的虛擬環境。以前述中需要被解決的例子中，應用
程式 A 能夠擁有它自己的虛擬環境，並且是裝好 1.0 版，然而應用程式 B 則
可以是用另外一個有 2.0 版的虛擬環境。要是應用程式 B 需要某個函式庫被升
級到 3.0 版，這並不會影響到應用程式 A 的環境。


12.2. 建立虛擬環境
==================

用來建立與管理虛擬環境的模組叫做 "venv"。"venv" 通常會安裝你能夠取得的
最新版本的 Python。要是你的系統有不同版本的 Python，你可以透過
"python3" 這個指令選擇特定或是任意版本的 Python。

在建立虛擬環境的時候，在你決定要放該虛擬環境的資料夾之後，在 script 中
執行 "venv" 模組並且給定資料夾 path：

   python3 -m venv tutorial-env

如果 "tutorial-env" 不存在的話，這會建立 "tutorial-env" 資料夾，並且也
會在裡面建立一個有 Python 直譯器的複本、標準函式庫、以及不同的支援檔案
的資料夾。

虚拟环境的常用目录位置是 ".venv"。 这个名称通常会令该目录在你的终端中
保持隐藏，从而避免需要对所在目录进行额外解释的一般名称。 它还能防止与
某些工具所支持的 ".env" 环境变量定义文件发生冲突。

一旦你建立了一個虛擬環境，你可以啟動他。

在 Windows 系統中，使用：

   tutorial-env\Scripts\activate.bat

在 Unix 或 MacOS 系統，使用：

   source tutorial-env/bin/activate

（這段程式碼適用於 bash shell。如果你是用 **csh** 或者 **fish** shell
，應當使用替代的 "activate.csh" 與 "activate.fish" 腳本。）

啟動虛擬環境會改變你的 shell 提示字元來顯示你正在使用的虛擬環境，並且
修改環境以讓你在執行 "python" 的時候可以得到特定的 Python 版本，例如說
：

   $ source ~/envs/tutorial-env/bin/activate
   (tutorial-env) $ python
   Python 3.5.1 (default, May  6 2016, 10:59:36)
     ...
   >>> import sys
   >>> sys.path
   ['', '/usr/local/lib/python35.zip', ...,
   '~/envs/tutorial-env/lib/python3.5/site-packages']
   >>>


12.3. 用 pip 管理套件
=====================

你可以使用一个名为 **pip** 的程序来安装、升级和移除软件包。 默认情况下
"pip" 将从 Python Package Index <https://pypi.org> 安装软件包。 你可以
在你的 web 浏览器中查看 Python Package Index。

"pip" 有许多子命令: "install", "uninstall", "freeze" 等等。 （请在 安
裝 Python 模組 指南页查看完整的 "pip" 文档。）

你可以透過指定套件名字來安裝最新版本的套件：

   (tutorial-env) $ pip install novas
   Collecting novas
     Downloading novas-3.1.1.3.tar.gz (136kB)
   Installing collected packages: novas
     Running setup.py install for novas
   Successfully installed novas-3.1.1.3

你也可以透過在套件名稱之後接上 "==" 和版號來指定特定版本：

   (tutorial-env) $ pip install requests==2.6.0
   Collecting requests==2.6.0
     Using cached requests-2.6.0-py2.py3-none-any.whl
   Installing collected packages: requests
   Successfully installed requests-2.6.0

要是你重新執行此指令，"pip" 會知道該版本已經安裝過，然後什麼也不做。你
可以提供不同的版本號碼來取得該版本，或是可以執行 "pip install
--upgrade" 來把套件升級到最新的版本：

   (tutorial-env) $ pip install --upgrade requests
   Collecting requests
   Installing collected packages: requests
     Found existing installation: requests 2.6.0
       Uninstalling requests-2.6.0:
         Successfully uninstalled requests-2.6.0
   Successfully installed requests-2.7.0

"pip uninstall" 後面接一個或是多個套件名稱可以從虛擬環境中移除套件。

"pip show" 可以顯示一個特定套件的資訊：

   (tutorial-env) $ pip show requests
   ---
   Metadata-Version: 2.0
   Name: requests
   Version: 2.7.0
   Summary: Python HTTP for Humans.
   Home-page: http://python-requests.org
   Author: Kenneth Reitz
   Author-email: me@kennethreitz.com
   License: Apache 2.0
   Location: /Users/akuchling/envs/tutorial-env/lib/python3.4/site-packages
   Requires:

"pip list" 會顯示虛擬環境中所有已經安裝的套件：

   (tutorial-env) $ pip list
   novas (3.1.1.3)
   numpy (1.9.2)
   pip (7.0.3)
   requests (2.7.0)
   setuptools (16.0)

"pip freeze" 可以複製一整個已經安裝的套件清單，但是輸出使用 "pip
install" 可以讀懂的格式。一個常見的慣例是放這整個清單到一個叫做
"requirements.txt" 的檔案：

   (tutorial-env) $ pip freeze > requirements.txt
   (tutorial-env) $ cat requirements.txt
   novas==3.1.1.3
   numpy==1.9.2
   requests==2.7.0

"requirements.txt" 可以提交到版本控制，並且作為釋出應用程式的一部分。
使用者可以透過 "install -r" 安裝對應的的套件：

   (tutorial-env) $ pip install -r requirements.txt
   Collecting novas==3.1.1.3 (from -r requirements.txt (line 1))
     ...
   Collecting numpy==1.9.2 (from -r requirements.txt (line 2))
     ...
   Collecting requests==2.7.0 (from -r requirements.txt (line 3))
     ...
   Installing collected packages: novas, numpy, requests
     Running setup.py install for novas
   Successfully installed novas-3.1.1.3 numpy-1.9.2 requests-2.7.0

"pip" 還有更多功能。可以參考安裝 Python 模組說明書來取得完整的 "pip"
參考資料。當你撰寫了一個套件並且想要讓它可以在 Python Package Index 上
可以取得的話，可以參考發布 Python 模組說明。
