Python多環境管理神器(pipenv)

pipenv

參考官網://pipenv.pypa.io/

pipenv 是一款比較新的包管理工具,其借鑒了 javascript 的 npm 和 PHP 的 composer 等理念,通過一個依賴描述文件 Pipfile 來安裝和管理依賴,以達到協同開發的目的。如果你熟悉 npm 或者 composer 的話,那 pipenv 正合你胃口。pipenv 其實整合了 pip 和 virtualenv 等庫,在其上推出了更便捷的使用方式。

1、安裝pipenv

直接使用pip命令安裝

pip3 install pipenv 

設置命令行的自動補全功能

如果使用的bash shell,請將以下代碼添加到 .bashrc 或 .bash_profile 文件內:

eval "$(pipenv --completion)" 

參考://blog.csdn.net/swinfans/article/details/89305301

命令詳解:

$ pipenv
Usage: pipenv [OPTIONS] COMMAND [ARGS]...

Options:
  --where             輸出項目根目錄相關信息
  --venv              輸出virtualenv相關信息
  --py                輸出Python解釋器相關信息
  --envs              輸出環境變量選項
  --rm                刪除virtualenv
  --bare              最小化輸出
  --completion        命令自動補全
  --man               顯示man頁面
  --three / --two     在創建virtualenv時使用Python3或Python2
  --python TEXT       指定創建virtualenv時使用的具體的Python版本
  --site-packages     為virtualenv啟用site-packages [env變量:PIPENV_SITE_PACKAGES]
  --clear             清除緩存(pipenv,pip和pip-tools)[env變量:PIPENV_CLEAR]
  --pypi-mirror TEXT  指定一個PyPI鏡像
  --version           顯示版本信息並退出
  -h, --help          顯示幫助信息並退出


使用示例:
   創建一個項目,並明確指定使用Python3.7:
   $ pipenv --python 3.7

   刪除項目的virtualenv (inferred from current directory):
   $ pipenv --rm

   為項目安裝所有依賴項 (including dev):
   $ pipenv install --dev

   創建包含pre-releases的lockfile文件:
   $ pipenv lock --pre

   將已安裝的依賴項顯示為圖表:
   $ pipenv graph

   檢查已安裝的依賴項是否存在安全漏洞:
   $ pipenv check

   安裝一個本地的setup.py到你的虛擬環境或Pipfile:
   $ pipenv install -e .

   使用原生的pip命令:
   $ pipenv run pip freeze

Commands:
  check      根據 Pipfile 中提供的PEP 508標記檢查安全漏洞
  clean      卸載所有 Pipfile.lock 未指定的包
  graph      顯示當前安裝的依賴項的關係圖信息
  install    如果未指定要安裝的包,則會安裝 Pipfile 中的所有包,否則,只安裝指定的包
  lock       生成 Pipfile.lock 文件
  open       在編輯器中查看給定的模塊
  run        運行virtualenv中已安裝的命令
  shell      在virtualenv內啟動一個shell
  sync       安裝 Pipfile.lock 中指定的所有的包
  uninstall  卸載一個指定的包並將其從 Pipfile 中移除
  update     先運行lock命令,在運行sync命令

2、pipenv虛擬環境管理

2.1、虛擬環境創建與激活

創建虛擬環境

# 進入項目目錄:
[root@ops-130 data]# mkdir myproj10
[root@ops-130 data]# cd myproj10/
[root@ops-130 myproj10]# ls
[root@ops-130 myproj10]# pipenv install

上面的命令會自動在~/.local/share/virtualenvs/目錄下創建虛擬環境目錄,

名字為一個當前目錄名加一串隨機字符串的虛擬環境目錄。這裡是myproj10-740tHe3W

創建過程如下圖:

clipboard

下面多了兩個文件,為Pipfile和Pipfile.lock,用於存放依賴包名的文件。

類似php里的composer.json和composer.lock。

[root@ops-130 myproj10]# ls
Pipfile  Pipfile.lock

查看虛擬環境

[root@ops-130 myproj10]# pipenv --venv
/root/.virtualenvs/myproj10-740tHe3W

我們的虛擬環境目錄在/root/.virtualenvs/下面,是因為我們之前設置過環境變量

export WORKON_HOME=$HOME/.virtualenvs 

激活虛擬環境:

cd /data/myproj10
pipenv shell

激活後如下圖:

clipboard

注意:上面激活虛擬環境的時候,出現了這麼一個告警:

Warning: Your Pipfile requires python_version 2.7, but you are using 3.9.9 (/root/./m/bin/python).

原因:這是因為創建虛擬環境的時候,沒有指定python解釋器,Pipfile就使用系統默認的python解釋器了,就是2.7.5,但是pipenv卻是使用系統最新的解釋器3.9.

解決辦法:

辦法一:手動修改Pipfile

手動修改Pipfile文件里的python_version

注意:Pipfile.lock里的也要修改

vim Pipfile

[[source]]
url = "//pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]

[dev-packages]

[requires]
python_version = "3.9"

辦法二:刪除虛擬環境,重新創建虛擬環境

刪除虛擬環境後,再次安裝會覆蓋之前的Pipfile,使用新環境。如果不刪除,無法覆蓋。

# pipenv --rm刪除當前虛擬環境,注意Pipfile不會被刪掉
[root@ops-130 myproj10]# pipenv --rm
# 使用pipenv重新安裝,指定解釋器版本為3.X
[root@ops-130 myproj10]# pipenv install --three
# 此時再次查看Pipfile版本就和環境一致了。
[root@ops-130 myproj10]# cat Pipfile

如下圖:

clipboard

退出虛擬環境:exit

((myproj10) ) [root@ops-130 myproj10]# exit
exit
[root@ops-130 myproj10]#

剛創建好虛擬環境的時候,會自動進入虛擬環境,並且此時是沒有前綴顯示,此時需要用exit退出。

當後面用pipenv shell激活的時候,會顯示前綴,此時可以用exit退出,也可以使用deactivate退出。

clipboard

刪除虛擬環境

[root@ops-130 myproj10]# pipenv --rm 
Removing virtualenv (/root/.virtualenvs/myproj10-740tHe3W)...

2.2、創建虛擬環境的多種方式

pipenv創建虛擬環境有多種方式,這裡總結一下:

方式一:指定解釋器創建虛擬環境

# 創建虛擬環境
pipenv --three
# 或者
pipenv --python 3.9

這種方式是指定python解釋器,並創建虛擬環境。

它會在當前目錄生成Pipfile,不會生成Pipfile.lock

這種方式創建虛擬環境後,會自動進入虛擬環境,但是進入後也不會顯示前綴

clipboard

方式二:安裝所有依賴時創建虛擬環境

# 創建虛擬環境
pipenv install

這種方式是在安裝依賴包的同時創建虛擬環境。

因為pipenv install,就是根據Pipfile來安裝所有依賴,類似npm install

如果當前目錄沒有Pipfile,它就會自動創建Pipfile並創建虛擬環境。

因為這種方式它已經在安裝所有依賴了,所以不僅會創建Pipfile,也會創建Pipfile.lock文件。

同時,它創建虛擬環境後,也會自動進入環境,但是也不會顯示前綴。

如下圖:

clipboard

方式三:激活時創建虛擬環境

# 激活,如果環境不存在,則創建虛擬環境並激活
pipenv shell

這個命令主要用於激活環境,但是如果環境不存在,則會先創建虛擬環境,並同時激活虛擬環境。

這種方式因為使用了pipenv shell激活了,所以創建虛擬環境後,也會自動進入虛擬環境,並激活。

會顯示虛擬環境前綴。

如下圖:

clipboard

2.3、修改虛擬環境目錄位置

有三種方法:

方法一:

# 方法一:
# 設置這個環境變量,pipenv會在當前目錄下創建.venv的目錄,以後都會把模塊裝到這個.venv下。
export PIPENV_VENV_IN_PROJECT=1

方法二:

# 自己在項目目錄下手動創建.venv的目錄,然後運行 pipenv run 或者 pipenv shell pipenv都會在.venv下創建虛擬環境。
mkdir .venv
pipenv shell

方法三:

# 設置WORKON_HOME到其他的地方 (如果當前目錄下已經有.venv,此項設置失效)。
export WORKON_HOME=$HOME/.virtualenvs

注意:

小技巧: 如果子級目錄的父級目錄已經創建過虛擬環境, 則子級目錄無法創建虛擬目錄(子級目錄無法生成Pipfile, 子級默認會使用父級的虛擬環境), 如果確實需要在子級目錄創建獨立的虛擬環境,可以運行pipenv –where 獲取父級虛擬環境的名字, 根據虛擬環境的前半部分名字, 確定父級目錄的位置, 然後刪除父級目錄下的Pipfile, Pipfile.lock, 運行exit退出父級虛擬環境,然後回到子目錄,運行pipenv –three創建子目錄的虛擬環境即可

2.4、相關定位操作

定位項目目錄:

[root@ops-130 aaa]# pipenv --where
/data/myproj10

定位虛擬環境目錄,即virtualenv目錄

[root@ops-130 aaa]# pipenv --venv
/root/.virtualenvs/myproj10-740tHe3W

定位Python解釋器:

[root@ops-130 aaa]# pipenv --py
/root/.virtualenvs/myproj10-740tHe3W/bin/python

如下圖:

clipboard

3、pipenv包管理

安裝依賴包:

安裝相關依賴包,並加入到Pipfile

pipenv install flask

它會在當前環境安裝flask依賴包,並記錄flask包名以及版本信息,記錄到Pipfile里。

如果安裝的時候,沒有指定包名,默認是最新的,會記錄為「*」

注意:Pipfile只會記錄你install里指定的包,但是這個flask包本身所依賴的包不會記錄,

但是所有的依賴詳情都會記錄到Pipfile.lock中。

clipboard

Pipfile.lock類似如下:

clipboard

查看目前安裝的庫及其依賴關係

pipenv graph

如下圖:這是所有的完整依賴關係,這些會記錄在Pipfile.lock中。

clipboard

Pipfile會記錄當前虛擬環境安裝的所有依賴包及其對應的版本,當我們需要遷移項目,部署新項目,或者有新人接手時,就可以直接拿到這個Pipfile和Pipfile.lock文件,直接pipenv install即可,它就會按照Pipfile里的包,把所有的依賴文件都安裝上,是不是很方便。

安裝所有依賴包:

# 根據Pipfile的記錄,安裝所有依賴包
pipenv install

指定安裝包版本:

你可以使用 語義化(//semver.org/)的版本控制方案 指定包的版本。例如 major.minor.micro 。

例如,你可以使用如下的命令安裝 requests:

pipenv install requests~=1.2   # 相當於 requests~=1.2.0

Pipenv 將安裝 1.2 版本和任何 minor 版本的更新,但不會安裝 2.0 版本。

上面的命令將會自動更新 Pipfile 文件以體現這個特殊的需求。

通常,Pipenv使用與pip相同的參數格式。但是,請注意,根據PEP 440,您不能使用包含連字符或加號的版本號。

要指定包含或者排除具體的版本,您可以使用如下命令:

pipenv install "requests>=1.4"   # 只安裝等於或者大於 1.4.0 的版本
pipenv install "requests<=2.13"  # 只安裝小於或者等於 2.13.0 的版本
pipenv install "requests>2.19"   # 安裝 2.19.1 版本但是不安裝 2.19.0 版本

注意:強烈建議使用雙引號包裹包名和版本號以避免unix操作系統中的輸入和輸出重定向問題。

請優先使用 ~= 標識符而不是 == 標識符,因為後者會阻止 pipenv 更新包:

pipenv install "requests~=2.2"  # 鎖定包的主版本(這相當於使用==2.*)

要避免安裝某個特定的版本,可以使用 != 標識符。

要深入解釋有效標識符和更複雜的用例,請查看 PEP-440 的相關部分。

//www.python.org/dev/peps/pep-0440/#version-specifiers%3E

卸載依賴包:

卸載指定包:

pipenv uninstall flask

卸載包後,相關包和依賴詳情會從Pipfile和Pipfile.lock中移除。

clipboard

卸載當前環境所有包:

# 從虛擬環境中移除所有已安裝的包,但 Pipfile.lock 文件不受影響
pipenv uninstall --all

卸載開發包:

# 從虛擬環境中卸載所有開發包,並從 Pipfile 文件中移除這些包
pipenv uninstall –all-dev

更新依賴包:

查看所有需要更新的包:

pipenv update --outdated

如下圖:

clipboard

更新指定包:

pipenv update <包名>

更新所有包:

pipenv update

檢查安全漏洞:

pipenv check  # 檢查安全漏洞

它可能會檢查出很多錯誤,其實如果不影響你使用,你可以直接忽略掉。強迫症患者也可以一個一個問題去解決。

比如如下問題:

clipboard

修改pipenv的鏡像源

可以修改當前目錄下Pipfile文件,將[source]下的url屬性改成國內的源即可:

[[source]]
url = "//mirrors.aliyun.com/pypi/simple"
verify_ssl = true
name = "pypi"

3、環境部署

使用pipenv進行多環境部署

dev與正式環境區分安裝。

當你想要一個包只在開發環境使用,等生產部署的時候,不需要該安裝包,你可以這樣指定環境安裝。

# 把django安裝在開發環境
pipenv install django --dev

安裝如下圖

clipboard

安裝完成後,查看Pipfile文件:

會發現,pipenv已經將安裝包區分開來了。

[dev-packages] 里記錄的–dev開發環境安裝的包

[package] 里記錄的是沒有加環境參數,默認就是正式環境的包。

clipboard

那麼等到你真正遷移到生產環境部署的時候,就只需要這麼做:

pipenv install

這樣默認是只安裝[package] 里的安裝包的,會自動過濾掉[dev-packages] 里的包。

讓生產環境變得更加純凈,避免有多餘的包。

如下:這是直接pipenv install的,裏面是沒有django包的

clipboard

如果你要遷移到開發環境,只需要這麼做:

pipenv install --dev

它就會把[dev-packages] 里的包也一起安裝上了。

如下:

這是使用了–dev參數的,看到已經把djiango安裝上了。

clipboard

4、Pipfile.lock文件

Pipfile.lock 利用了pip中一些新的安全改進。默認情況下,Pipfile.lock 包含每個下載的包的 sha256 哈希值。這可以使pip能夠保證從不信任的PyPI源安裝包時或者在不穩定的網絡環境下安裝包時都能保證包的正確性與完整性。我們強烈建議通過將項目從開發環境提升到生產環境來進行部署。您可以使用 pipenv lock 編譯開發環境上的依賴項,並將編譯後的 Pipfile.lock 文件部署到您所有的生產環境,以便進行可重現的構建。

(使用Pipfile.lock可以鎖定之前的安裝包,確保遷移重新部署後,能夠重現跟之前一樣的環境。)

Pipfile和Pipfile.lock不一致

因為使用pipenv install的時候,加上–ignore-lock參數,可以忽略 Pipfile.lock 文件而直接安裝 Pipfile 中的包。此外,不會更新 Pipfile.lock 文件。

當pipenv install安裝一些比較大的包,比如TensorFlow等科學包,在安裝完包,正在解析包依賴的時候,可能會花費很長時間,可能就會ctrl+C停止掉了,此時包已經安裝完成,Pipfile已經寫入完成,但是沒有解析完依賴,所以Pipfile.lock沒有寫入完成。

這兩種情況都會導致Pipfile和Pipfile.lock不一致的情況,會對應不上。

此時,可以使用Pipenv lock重新生成Pipfile.lock文件。

pipenv lock

如果通過 pipenv 命令安裝和卸載 package,安裝或卸載完成後還會更新 Pipfile.lock 文件,有時候會卡在這個步驟。通常可以 ctrl+c 強制推出,刪除 Pipfile.lock, 然後

# 重新生成Pipfile.lock文件
pipenv lock

默認情況下,使用pipenv install,它會重新解析Pipfile里安裝包的依賴性,並將依賴關係更新到Pipfile.lock中。如果你不想要重新解析Pipfile里安裝包,只想安裝Pipfile.lock文件中現存的依賴包,可以精確的指定只使用Pipfile.lock文件。

pipenv sync

可以使用 sync 命令精確安裝 Pipfile.lock 文件中指定的包:

pipenv sync 

注意:pipenv install –ignore-pipfile 和 pipenv sync 命令很相似,但是pipenv sync 命令永遠不會嘗試重新鎖定依賴項,因為它被認為是一個原子操作。默認情況下,除非使用了 –deploy 標誌,否則 pipenv install 會嘗試重新鎖定依賴項。

pipenv install --deploy

可以使用 –deploy 標誌強制Pipfile.lock 文件是最新的。

上述命令將在Pipfile.lock 文件不是最新的時候導致構建失敗,而不是生成一個新的。

5、兼容requirements.txt

之前我們的pip工具可以從requierments.txt文件中導入依賴包。

在pipenv,用下面的命令就可以將Pipfile和Pipfile.lock文件裏面的包導出為requirements.txt文件。

# 將Pipfile里的全部包導出到requirements.txt
pipenv lock -r > requirements.txt

內容如下:

clipboard

可以選擇只導出開發環境的包:

# 只導出開發環境的包
pipenv lock -r --dev-only > requirements.txt

如下圖:

clipboard

導出開發環境+ 默認的環境的包:

# dev環境和default環境的包都會導出
pipenv lock -r --dev > requirements.txt

如下圖:

clipboard

也可以使用底層pip的命令導出:

pipenv run pip freeze > requirements.txt

如下圖:

clipboard

導入requirements.txt

導出為requirements.txt後,可以通過pip導入,也可以通過pipenv導入。

# 通過pip導入
pip install -r requirements.txt
# 通過pipenv導入
pipenv install -r requirements.txt

6、虛擬環境中運行命令:

啟動shell運行

正常來說,如果想要讓命令運行在虛擬環境,需要啟動一個虛擬環境的shell,否則命令還是在系統環境下運行的,如下:

pipenv shell

如下圖:

clipboard

使用run運行:

如果不想啟動shell,而是直接在虛擬環境中執行命令,可以使用run:

# pipenv run <命令>
pipenv run python --version

如下圖:

clipboard

部署項目的時候,你也可以不進入虛擬環境的方式運行項目:

pipenv run python xxx.py

7、環境變量:(.env)

自動加載.env文件 (利器)

.env文件可以設置一些環境變量,在程序開發的時候模擬環境變量。

如果項目目錄下包含一個 .env 文件,它會被 pipenv shell 和 pipenv run 命令自動加載:

# 如下,設置一個變量HELLO,以及配置文件路徑的變量
[root@ops-130 myproj10]# cat .env 
HELLO=WORLD
CONFIG_PATH=${HOME}/.config/foo


# 測試環境變量
# 使用pipenv run的時候,會自動加載該環境變量。
[root@ops-130 myproj10]# pipenv run python
Loading .env environment variables...
Python 3.9.9 (main, Dec 31 2021, 15:34:46) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['HELLO']
'WORLD'
>>> os.environ['CONFIG_PATH']
'/root/.config/foo'
>>> 

這類似於php的lavel框架的.env文件。

這對於將生產憑證排除在代碼庫之外非常有用。我們不建議將 .env 文件提交到源代碼控制中!

如果你的 .env 文件位於不同的路徑下或者有其他名稱,你可以設置一個PIPENV_DOTENV_LOCATION 環境變量:

PIPENV_DOTENV_LOCATION=/path/to/.env pipenv shell

要禁止pipenv加載 .env 文件,可以設置 PIPENV_DONT_LOAD_ENV 環境變量:

PIPENV_DONT_LOAD_ENV=1 pipenv shell

Pipfile引用環境變量:

在Pipfile中也可以引用環境變量的值,格式為${MY_ENVAR}或$MY_ENVAR,在Windows系統中還支持%MY_ENVAR%。

[[source]]
url = "//${PYPI_USERNAME}:${PYPI_PASSWORD}@my_private_repo.example.com/simple"
verify_ssl = true
name = "pypi"

[packages]
flask = "*"
jieba = "*"

[dev-packages]
django = "*"

[requires]
python_version = "3.9"

這裡的變量為:${PYPI_USERNAME}:${PYPI_PASSWORD}

使用前提是,系統中要已經設置了相關的變量。

當然你可以結合.env文件,將相關變量設置在.env里。

從setup.py安裝依賴包

很多依賴庫都包含setup.py文件,裏面也包含了對應包的子依賴信息,這個文件跟Pipfile.lock有點相似,pipenv也提供了堆setup.py的支持。

pipenv也可以從setup.py安裝:

pipenv install -e .

更多pipenv的用法,請參考官網://pipenv.pypa.io/en/latest/

8、優缺點分析:

1、pipenv集成了pip,virtualenv兩者的功能,且完善了兩者的一些缺陷。

2、支持Python2 和 Python3,在各個平台的命令都是一樣的。

3、類似npm,容易遷移,便於項目內部協同工作

4、各個地方使用了哈希校驗,無論安裝還是卸載包都十分安全,且會自動公開安全漏洞。

5、通過加載.env文件簡化開發工作流程。

6、Bug 很多,確實比較年輕,安裝的流程有些讓人困惑,不像 pip 這麼直接好理解

參考引用:

//blog.csdn.net/swinfans/article/details/89305301

//pipenv.pypa.io/en/latest/

Tags: