前言
這篇是用來推廣 pipenv 的使用的。
以下文章適用 Linux/Unix 系統,如果你是 Windows 用戶的話,一些指令請自行替換。
先假設你已經會 python 了。
至少,你看得懂
|
|
假設你把上面的程式碼儲存成 hello.py
了。你知道(也必須知道)怎麼使用 terminal,或是終端機,去運作他。
|
|
python 是如此的簡單迷人。
然而在使用了 python 一陣子之後,肯定會出現以下的情形吧。
假設有兩個專案,簡單區分,叫做 project_old 跟 project_new。檔案結構如下:
|
|
[email protected]
代表著使用了版本 3.7 的 python。
project_old資料夾裡有 old.py
,使用了 [email protected]
,並且導入了 [email protected]
(當然沒有這個package,我杜撰的,一時想不到有什麼好舉例的)。
在 old.py
中使用了一個 deprecated_function
。知道這個 function 會在一個版本後被淘汰,所以只有在 1.2 版本前才能使用。而這個 function可能出現很多次,又或者你深知他其實比較好用,因次你選擇讓這個檔案停留在 [email protected]
的版本。
|
|
然而同時有另一個專案,就叫做project_new,使用了 [email protected]
,因為他有一個新的 new_function
可以使用。並且因為使用了新的 format 方法,需要使用較高版本,假設使用 [email protected]
。
|
|
我們知道 python 的 module 是利用 pip
進行安裝的。一開始為了 project_old 安裝了 [email protected]
,並且又安裝了 [email protected]
。但為了 project_new,把 python 升級成 [email protected]
。在大部分情況下,python 是幾乎能向前相容的,除非使用了被淘汰的特性(通常會寫在更新日誌中),因此升級成較高版本的 python 是合理的。
但 module 就不一樣了。module並沒有被設計為向前相容(當然大多數會為了向前相容而設計,但這就要看開發者的心情了,不是嗎)。因此在安裝的時候就不可能只安裝最新的版本。
打個比方,numpy
就為了不同的 python 有不同的版本。[email protected]
就只支援 [email protected]
。
所以上述的例子,不可能利用升級 module 的手段進行兼容,也就是 pip install package==1.5
會使得 project_old 變得不可運行。
這就是環境在同一個的弊病。
我的環境簡直髒爆了
那有沒有什麼解決方案?
有的,而且很多。在現今環境及版本管理幾乎是主流的現在,python 也擁有非常多的版本管理生態系。
- virtualenv:老牌 pip 環境管理工具
- venv:官方的環境管理工具
- pyenv:管理多 python 版本的工具
- pipenv:本日主角
前三者就不多說明了,有興趣的可以自行搜尋文件。
本日主役:pipenv
pipenv做了什麼?
pipenv 整合了
- python 版本管理(透過 pyenv 完成)
- pip 環境管理(類似 virtualenv)
並且被官方支援更新。
接著透過實際操作來了解 pipenv 到底做了什麼。
Install
首先安裝 pipenv
來直接開始吧。打開你的終端機,或是 terminal 先。
如果你已經電腦有 python 的話,不介意再多安裝一個 module 吧。
|
|
又或者你是個 mac 使用者,想使用萬能的 brew
安裝也行。
|
|
不管是哪種方法,安裝完之後確認有沒有安裝成功。
|
|
出現了安裝版本就是安裝成功了。
Usage
我安裝好了,我該怎麼使用它?
首先,你要有你的 project 資料夾。pipenv 會認定 project 的資料夾就是一個環境。
|
|
接著,要開始初始化環境了。直接在 project 資料夾下輸入
|
|
等待完成,環境就建立好了,非常的簡單。
如果你的電腦沒有該 python 版本的話,pipenv 不會初始化成功。也就是電腦的版本是 python3.8
的話,就會需要已經安裝過之後,才能在 pipenv 中指定版本。
如果有需要任意切換版本的話,請愛用 pyenv 來輔助。安裝完之後可以直接搭配 pipenv 使用,也就是可以任意指定版本,pyenv 會詢問是否要安裝。
接著安裝任意套件吧,安裝步驟跟 pip 高度相似。
|
|
但只有一點不太一樣,如果要列出 project 中安裝了什麼套件的話,不能使用 pipenv list
而是使用 pipenv graph
。
接著在環境中執行程式吧,將下列程式碼儲存成 main.py
。
|
|
直接執行。
|
|
可以看出來,原本只要輸入 python main.py
就能執行的程式,為了要讓他執行在環境內,必須要加上 pipenv run
。如果沒加的話,就是跑在全域環境中喔。
此外如果覺得加上 pipenv run
太煩,可以試試看 pipenv shell
。
這個指令會讓 shell 進到環境中,在環境內部直接執行 python main.py
也算是在環境內部執行的。如果要離開環境,直接 exit
就行了。
Pipfile
在建立環境後,會有個 Pipfile
的檔案,內容如下。
|
|
[package]
記錄著安裝的套件,而 requires
則紀錄了 python 的版本。
與 Pipfile 同時出現的還有 Pipfile.lock
。這是用來檢查安裝套件的 sha256。基本上這是用來避免套件不一致。
試想,安裝 pip module 時,其實是連結到網路的某個位置,尋找相同名字進行下載。如果 dns 遭到竄改,下載到含有惡意代碼的 module,這時 lock file 就會發揮它的作用,來避免下載到非預期的套件。
pipenv對我做了什麼?
首先,python 的環境建立在修改python以及pip的路徑。
也就是,當建立的一個環境之後,環境內的 python
以及 pip
會被映射到環境指定的位置。
簡單測試一下:
|
|
可以看到在 pipenv shell
之前,pip
的位置是系統設定的,以及 python
根本沒有其對應位置(我使用 mac,預設就是 python3)。
而經過環境修改後,pip
以及 python
都被替換成環境內的 binary file 了。
我要怎麼分享我的環境?
將你的程式碼以及 Pipfile
包在一起發送給其他人,當其他人得到你的 Pipfile
時,直接輸入
|
|
就可以安裝回環境了,是不是很方便呢。
在 github 上,若是有 project 有 Pipfile 的話,表示他使用 pipenv 管理環境,因此可以很簡單的複製環境。
練習
建立一個自己的專案,使用 pipenv 安裝需要的套件,並且自己執行看看。