Requests庫做者Kenneth Reitz的另外一神做!虛擬環境及包管理工具Pipenv!

咱們在運行 Python 項目的時候常常會遇到一些版本問題,例如 A 項目依賴於 Django 1.5,而 B 項目又依賴 Django 2.0,而咱們的系統卻只有一個 Python 解釋器,咱們全部的包都被裝在了 Python 安裝目錄的 site-packages 目錄下,因此 Django 只能是某個特定的版本,因此這樣就會致使運行的時候致使 A 或 B 項目出現兼容問題。爲了解決這個問題,咱們可能會使用 virtualenv 來爲項目建立一套獨立的 Python 運行環境,或者咱們可能會使用 Docker 容器來實現不一樣項目的隔離運行,但總的來講,它們使用起來其實並無那麼方便。另外在進行 Python 包管理時,requirements.txt 這樣的包依賴標識文件也顯得很雞肋,在某些狀況下可能會帶來一些麻煩。爲了解決這些問題,一個更加使用方便的包管理工具誕生了,叫作 Pipenv,接下來就讓咱們一塊兒來了解一下它的用法。

簡介

Pipenv,它的項目簡介爲 Python Development Workflow for Humans,是 Python 著名的 requests 庫做者 kennethreitz 寫的一個包管理工具,它能夠爲咱們的項目自動建立和管理虛擬環境並不是常方便地管理 Python 包,如今它也已是 Python 官方推薦的包管理工具。python

Pipenv 咱們能夠簡單理解爲 pip 和 virtualenv 的集合體,它能夠爲咱們的項目自動建立和管理一個虛擬環境。virtualenv 在使用時咱們須要手動建立一個虛擬環境而後激活,Pipenv 會自動建立。另外咱們以前可能使用 requirements.txt 文件來標識項目所須要的依賴,可是這樣會帶來一些問題,若有的 requirements.txt 中只是將庫名列出來了,沒有嚴格指定版本號,這樣就可能會致使不一樣時間安裝的庫版本是不一樣的,如 requirements.txt 文件中對 Django 的依賴只寫了一個 django,可能在 2016 年的時候運行安裝會安裝 Django 的 1.x 版本,到了 2017 年就會安裝 Django 的 2.x 版本,因此可能致使一些麻煩。爲了解決這個問題,Pipenv 直接棄用了 requirements.txt,會同時它會使用一個叫作 Pipfile 和 Pipfile.lock 的文件來管理項目所需的依賴包,而再也不是簡單地使用 requirements.txt 文件來記錄項目所須要的依賴。shell

總的來講,Pipenv 能夠解決以下問題:django

  • 咱們不須要再手動建立虛擬環境,Pipenv 會自動爲咱們建立,它會在某個特定的位置建立一個 virtualenv 環境,而後調用pipenv shell 命令切換到虛擬環境。安全

  • 使用 requirements.txt 可能會致使一些問題,因此 Pipenv 使用 Pipfile 和 Pipfile.lock 來替代之,並且 Pipfile 若是不存在的話會自動建立,並且在安裝、升級、移除依賴包的時候會自動更新 Pipfile 和 Pipfile.lock 文件。app

  • 普遍使用 Hash 校驗,保證安全性。ide

  • 能夠更清晰地查看 Python 包及其關係,調用 pipenv graph 便可呈現,結果簡單明瞭。工具

  • 可經過自動加載 .env 讀取環境變量,簡化開發流程。ui

安裝

本文內容基於 Python 3.6 說明,默認的 Python 解釋器命令爲python3,包管理工具命令爲 pip3this

Pipenv 是基於 Python 開發的包,因此能夠直接用 pip 來安裝,命令以下:url

pip3 install pipenv

另外還有多種安裝方式,如 Pipsi、Nix、Homebrew,安裝方式能夠參考:http://pipenv.readthedocs.io/en/latest/#install-pipenv-today。

基本使用

首先咱們能夠新建一個項目,例如叫作 PipenvTest,而後新建一個 Python 腳本,例如叫 main.py,內容爲:

import django
print(django.get_version())

直接用系統的 Python3 運行此腳本:

python3 main.py

結果以下:

1.11

咱們能夠看到系統安裝的 Django 版本是 1.11。可是咱們想要本項目基於 Django 2.x 開發,固然咱們能夠選擇將系統的 Django 版本升級,但這樣又可能會影響其餘的項目的運行,因此這並非一個好的選擇。爲了避免影響系統環境的 Django 版本,因此咱們能夠用 Pipenv 來建立一個虛擬環境。

在該目錄下,輸入 pipenv 命令便可查看命令的完整用法:

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

Options:
 --update         Update Pipenv & pip to latest.
 --where          Output project home information.
 --venv           Output virtualenv information.
 --py             Output Python interpreter information.
 --envs           Output Environment Variable options.
 --rm             Remove the virtualenv.
 --bare           Minimal output.
 --completion     Output completion (to be eval'd).
 --man            Display manpage.
 --three / --two  Use Python 3/2 when creating virtualenv.
 --python TEXT    Specify which version of Python virtualenv should use.
 --site-packages  Enable site-packages for the virtualenv.
 --jumbotron      An easter egg, effectively.
 --version        Show the version and exit.
 -h, --help       Show this message and exit.


Usage Examples:
  Create a new project using Python 3.6, specifically:
  $ pipenv --python 3.6

  Install all dependencies for a project (including dev):
  $ pipenv install --dev

  Create a lockfile containing pre-releases:
  $ pipenv lock --pre

  Show a graph of your installed dependencies:
  $ pipenv graph

  Check your installed dependencies for security vulnerabilities:
  $ pipenv check

  Install a local setup.py into your virtual environment/Pipfile:
  $ pipenv install -e .

Commands:
 check      Checks for security vulnerabilities and against PEP 508 markers
            provided in Pipfile.
 graph      Displays currently–installed dependency graph information.
 install    Installs provided packages and adds them to Pipfile, or (if none
            is given), installs all packages.
 lock       Generates Pipfile.lock.
 open       View a given module in your editor.
 run        Spawns a command installed into the virtualenv.
 shell      Spawns a shell within the virtualenv.
 uninstall  Un-installs a provided package and removes it from Pipfile.
 update     Uninstalls all packages, and re-installs package(s) in [packages]
            to latest compatible versions.

接下來咱們首先驗證一下當前的項目是沒有建立虛擬環境的,調用以下命令:

pipenv --venv

結果以下:

No virtualenv has been created for this project yet!

這說明當前的項目還沒有建立虛擬環境,接下來咱們利用 Pipenv 來建立一個虛擬環境:

pipenv --three

pipenv --python 3.6

均可以建立一個 Python3 的虛擬環境,--three 表明建立一個 Python3 版本的虛擬環境,--python 則能夠指定特定的 Python 版本,固然 --two 則建立一個 Python2 版本的虛擬環境,但前提你的系統必須裝有該版本的 Python 才能夠。

執行完畢以後,樣例輸出以下:

Warning: the environment variable LANG is not set!
We recommend setting this in ~/.profile (or equivalent) for proper expected behavior.
Creating a virtualenv for this project…
Using /usr/local/bin/python3 to create virtualenv…
⠋Running virtualenv with interpreter /usr/local/bin/python3
Using base prefix '/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6'
New python executable in /Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python3.6
Also creating executable in /Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python
Installing setuptools, pip, wheel...done.
Virtualenv location: /Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E

這裏顯示 Pipenv 利用 /usr/local/bin/python3 做爲 virtualenv 的解釋器,而後在/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin 目錄下建立了一個新的 Python3 解釋器,同時還建立了兩個可執行文件別名 python3.6 和 python,另外咱們還能夠發現目錄下多了一個 Pipfile 文件,這時虛擬環境就建立完成了。

咱們切換到 PipenvTest-VSTVh89E/bin 目錄查看一下文件結構:

能夠看到這裏麪包含了pippip3pip3.6pythonpython3python3.6 等可執行文件,實際上目錄結構和使用 virtualenv 時是徹底同樣的,只不過文件夾的位置不一樣而已。

接下來咱們能夠切換到該虛擬環境下執行命令,執行以下命令便可:

pipenv shell

執行完畢以後樣例輸出以下:

Spawning environment shell (/bin/zsh). Use 'exit' to leave.
source /Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/activate                                                            
CQC-MAC% source /Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/activate
(PipenvTest-VSTVh89E) CQC-MAC%

實際上這也和 virtualenv 激活的流程同樣,也是調用了相似 source venv/bin/activate 方法將這個路徑加到全局環境變量最前面,這樣就會優先調用該路徑下的 pythonpython3python3.6 可執行文件了。

這時候咱們會發現命令行的樣子就變了,前面多了一個 (PipenvTest-VSTVh89E) 的標識,表明當前咱們已經切換到了虛擬環境下。

這時咱們用 which 或 where 命令查看一下 Python 可執行文件的路徑,命令以下:

(PipenvTest-VSTVh89E) CQC-MAC% which python3
/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python3
(PipenvTest-VSTVh89E) CQC-MAC% which python3.6
/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python3.6
(PipenvTest-VSTVh89E) CQC-MAC% which python
/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python

能夠發現當前的 Python 可執行路徑都被切換到了 PipenvTest-VSTVh89E/bin 目錄下,調用的是虛擬環境中的 Python 解釋器,這時咱們從新執行剛纔的腳本,命令以下:

(PipenvTest-VSTVh89E) CQC-MAC% python3 main.py

這時咱們能夠發現報了以下錯誤:

Traceback (most recent call last):
 File "main.py", line 1, in <module>
   import django
ModuleNotFoundError: No module named 'django'

這實際上是由於新的虛擬環境沒有安裝任何的 Python 第三方包,實際上若是直接使用 virtualenv 時也是這樣的結果。這是由於新的虛擬環境是一個全新的 Python 環境,它默認只包含了 Python 內置的包以及 pip、wheel、setuptools 包,其餘的第三方包都沒有安裝。

這時咱們可使用 Pipenv 來安裝 django 包,命令以下:

pipenv install django

運行後輸出結果以下:

Installing django…
Collecting django
 Downloading Django-2.0.2-py3-none-any.whl (7.1MB)
Collecting pytz (from django)
 Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
Installing collected packages: pytz, django
Successfully installed django-2.0.2 pytz-2018.3
Adding django to Pipfile's [packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (e101fb)!

若是有這樣的輸出結果就表明成功安裝了 Django,能夠看到此時安裝的 Django 版本爲 2.0,表明咱們的虛擬環境成功安裝了 Django 2.0 版本。

同時咱們還注意到它輸出了一句話叫作 Updated Pipfile.lock,這時咱們能夠發現項目路徑下又生成了一個 Pipfile.lock 文件,內容以下:

{
   "_meta": {
       "hash": {
           "sha256": "7b9623243d9c22b1f333ee710aff70d0cbcdf1dd7e0aac69230dc76855d27270"
       },
       "host-environment-markers": {
           "implementation_name": "cpython",
           "implementation_version": "3.6.1",
           "os_name": "posix",
           "platform_machine": "x86_64",
           "platform_python_implementation": "CPython",
           "platform_release": "17.4.0",
           "platform_system": "Darwin",
           "platform_version": "Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64",
           "python_full_version": "3.6.1",
           "python_version": "3.6",
           "sys_platform": "darwin"
       },
       "pipfile-spec": 6,
       "requires": {},
       "sources": [
           {
               "name": "pypi",
               "url": "https://pypi.python.org/simple",
               "verify_ssl": true
           }
       ]
   },
   "default": {
       "django": {
           "hashes": [
               "sha256:af18618ce3291be5092893d8522fe3919661bf3a1fb60e3858ae74865a4f07c2",
               "sha256:9614851d4a7ff8cbd32b73c6076441f377c45a5bbff7e771798fb02c43c31f47"
           ],
           "version": "==2.0.2"
       },
       "pytz": {
           "hashes": [
               "sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
               "sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda",
               "sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
               "sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
               "sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd",
               "sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5",
               "sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d",
               "sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef",
               "sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0"
           ],
           "version": "==2018.3"
       }
   },
   "develop": {}
}

能夠看到裏面標識了 Python 環境基本信息,以及依賴包的版本及 hashes 值。

另外咱們還能夠注意到 Pipfile 文件內容也有更新,[packages] 部分多了一句 django = "*",標識了本項目依賴於 Django,這個其實相似於 requirements.txt 文件。

那麼到這裏有小夥伴可能就會問了, Pipfile 和 Pipfile.lock 有什麼用呢?

Pipfile 其實一個 TOML 格式的文件,標識了該項目依賴包的基本信息,還區分了生產環境和開發環境的包標識,做用上相似 requirements.txt 文件,可是功能更爲強大。Pipfile.lock 詳細標識了該項目的安裝的包的精確版本信息、最新可用版本信息和當前庫文件的 hash 值,顧明思義,它起了版本鎖的做用,能夠注意到當前 Pipfile.lock 文件中的 Django 版本標識爲 ==2.0.2,意思是當前咱們開發時使用的就是 2.0.2 版本,它能夠起到版本鎖定的功能。

舉個例子,剛纔咱們安裝了 Django 2.0.2 的版本,即目前(2018.2.27)的最新版本。但可能 Django 之後還會有更新,好比某一天 Django 更新到了 2.1 版本,這時若是咱們想要從新部署本項目到另外一臺機器上,假如此時不存在 Pipfile.lock 文件,只存在 Pipfile文件,因爲 Pipfile 文件中標識的 Django 依賴爲 django = "*",即沒有版本限制,它會默認安裝最新版本的 Django,即 2.1,但因爲 Pipfile.lock 文件的存在,它會根據 Pipfile.lock 來安裝,仍是會安裝 Django 2.0.2,這樣就會避免一些庫版本更新致使不兼容的問題。

請記住:任何狀況下都不要手動修改 Pipfile.lock 文件!

好,接下來咱們再回歸正題,如今已經安裝好了 Django 了,那麼咱們從新運行此腳本即可以成功輸出 Django 版本信息了:

(PipenvTest-VSTVh89E) CQC-MAC% python3 main.py 

結果以下:

2.0.2

這樣咱們就成功安裝了 Django 2.x 了,和系統的 Django 1.11 沒有任何衝突。

在此模式的命令行下,咱們就可使用虛擬環境下的 Python 解釋器,並且所安裝的依賴包對外部系統沒有任何影響,並且使用 Pipfile 和 Pipfile.lock 來管理項目的依賴更加方便和健壯。

若是想要退出虛擬環境,只須要輸入 exit 命令便可:

(PipenvTest-VSTVh89E) CQC-MAC% exit
➜  PipenvTest python3 main.py
1.11

輸入退出命令以後,咱們從新再運行此腳本,就會從新使用系統的 Python 解釋器,Django 版本又從新回到了 1.11。

由此能夠看來,有了 Pipenv,咱們可使用 Pipfile 和 Pipfile.lock 來方便地管理和維護項目的依賴包,並且能夠實現虛擬環境運行,避免了包衝突問題,可謂一箭雙鵰。

經常使用命令

上文咱們介紹了 Pipenv 的基本操做,下面咱們再介紹一下它的一些經常使用命令。

虛擬環境路徑

咱們可使用 --venv 參數來得到虛擬環境路徑:

pipenv --venv 

樣例輸出以下:

/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E

可見這個路徑是一個標準的路徑,Pipenv 會把虛擬環境統一放到 virtualenvs 文件夾下,而不是本項目路徑下。

Python 解釋器路徑

要獲取虛擬環境 Python 解釋器路徑,可使用 --py 參數:

pipenv --py

樣例輸出以下:

/Users/CQC/.local/share/virtualenvs/PipenvTest-VSTVh89E/bin/python

加載系統 Python 包

默認狀況下,新建立的虛擬環境是不包含任何第三方包的,但咱們也能夠開啓加載系統 Python 包功能,使用 --site-packages 便可:

pipenv --site-packages

這樣建立的虛擬環境即可以使用系統已安裝的 Python 包了。

開啓虛擬環境

要開啓虛擬環境只須要執行以下命令:

pipenv shell

這樣就能夠進入虛擬環境,此時運行的 pythonpython3 命令都是虛擬環境下的。

安裝 Python 包

安裝 Python 包咱們再也不須要 pip 來安裝,直接使用 Pipenv 也可安裝,如安裝 requests,命令以下:

pipenv install requests

安裝完成以後會同時更新項目目錄下的 Pipfile 和 Pipfile.lock 文件。

有時候一些 Python 包是僅僅開發環境須要的,如 pytest,這時候咱們經過添加 --dev 參數便可,命令以下:

pipenv install pytest --dev

這時候,pytest 的依賴便會記錄在 Pipfile 的 [dev-packages] 區域:

[dev-packages]
pytest = "*"

獲取包依賴

咱們可使用命令來清晰地呈現出當前安裝的 Python 包版本及之間的依賴關係,命令以下:

pipenv graph

樣例結果以下:

Django==2.0.2
 - pytz [required: Any, installed: 2018.3]
pytest==3.4.1
 - attrs [required: >=17.2.0, installed: 17.4.0]
 - pluggy [required: <0.7,>=0.5, installed: 0.6.0]
 - py [required: >=1.5.0, installed: 1.5.2]
 - setuptools [required: Any, installed: 38.5.1]
 - six [required: >=1.10.0, installed: 1.11.0]
requests==2.18.4
 - certifi [required: >=2017.4.17, installed: 2018.1.18]
 - chardet [required: >=3.0.2,<3.1.0, installed: 3.0.4]
 - idna [required: <2.7,>=2.5, installed: 2.6]
 - urllib3 [required: <1.23,>=1.21.1, installed: 1.22]

能夠看到結果很是清晰,Django 當前安裝了 2.0.2版本,依賴於 pytz 任何版本,已經安裝了 2018.3 版本;pytest 已經安裝了 3.4.1 版本,依賴 attrs>=17.2.0 版本,已經安裝了 17.4.0 版本,另外還依賴 pluggy、py、setuptools、six 這些庫。總之包的依賴關係一目瞭然。

卸載 Python 包

卸載 Python 包也很是簡單,如卸載 requests 包,命令以下:

pipenv uninstall requests

卸載完成以後,Pipfile 和 Pipfile.lock 文件一樣會更新。

若是要卸載所有 Python 包,能夠添加 --all 參數:

pipenv uninstall --all

產生 Pipfile.lock

有時候可能 Pipfile.lock 文件不存在或被刪除了,這時候咱們可使用以下命令生成:

pipenv lock

以上即是一些經常使用的 Pipenv 命令,若是要查看更多用法能夠參考其官方文檔:https://docs.pipenv.org/#pipenv-usage。

結語

本文介紹了 Pipenv 的基本用法,做爲 pip 和 virtualenv 的結合體,咱們能夠利用它更方便地建立和管理 Python 虛擬環境,還能夠用更加科學的方式管理 Python 包,一箭雙鵰。

嗯,是時候拋棄 virtualenv 和 pip 了!

相關文章
相關標籤/搜索