當前位置:
首頁 > 知識 > Pipenv: 吹噓自己無所不能,實際上沒什麼卵用

Pipenv: 吹噓自己無所不能,實際上沒什麼卵用


Pipenv是一個Python打包工具,它可以很好地完成一件事-應用程序依賴管理。然而,它也受到各種問題、局限性和發展進程的影響。過去,Pipenv的宣傳材料在其目的和支持者方面具有很高的誤導性。


在這篇文章中,我將探討Pipenv的問題。它真的是Python.org所推薦的嗎?每個人——或者至少是絕大多數人——都能從中受益嗎?


內容




  • 「官方推薦工具」,或者說我們怎麼做到的



  • Pipenv能做什麼


            應用差異


            運行腳本(差勁)


           一切都做完了




  • pipenv不能做什麼


         Setup.py,資源分配,還有wheels文件


         在項目駐點之外運作


         Nikola



  • 我試著測時間的那一部分



  • 替代工具和新工具

          Hatch工具


          Poetry工具


          Pip要留在這裡了!



  • Pipenv的夭折速度



  • 結論



 「官方推薦工具」,或者說我們怎麼做到的


「Pipenv——是Python官方網站Python.org推薦的Python打包工具,免費(自由版)。」


在好幾個月期間Pipenv的README文檔中常常有上面那句口號:這句口號是2017-08-31加進去README文檔里的,最終在2018-05-19被刪除。有那麼一陣子(在2018-05-16),有說明(管理應用程序依賴,還有Pypa而非Python.org),而在約15分鐘的時間裡,這句口號變成了「Pipenv是世界上最爛的」或其他大概是這個意思的話(這是維護者的吐槽)。


README這句口號聲稱Pipenv是Python打包工具的關鍵。問題是:不是這樣的。Pipenv可能有時會有點用,但是對於其他許多人來說,試用這個工具只會讓人沮喪。我們稍後會探討這個問題。

這個口號值得吐槽的地方還有「Python.org」和「官方」這兩點。讓它變得「官方」的是有關Packaging.python.org的一個簡短教程[1],這是Pypa的打包用戶指南。還值得注意的是它引用了Python.org這個詞,這聽起來好像Pipenv得到了Python核心團隊的認可。Pypa(Python Packaging Authority)是一個獨立的組織——它們負責Python的打包文件(包括pypi.org、setuptools、pip、wheel、virtualenv等),所以這認可具有誤導性。當然,Pypa是Python的一個很有價值的部分;核心團隊的認可-比如,包含在官方Python發行版中-要重要得多。


這條標語引發了許多激烈的討論,可能是自5月在Reddit網貼出來後最受熱議最重大的帖子了。這種改變是由Reddit網的這個帖子引發的。我建議全文閱讀這個帖子。



Pipenv能做什麼


我們已經了解到Pipenv用於管理應用程序依賴。讓我們來了解一下這個詞的真正含義。



應用程序依賴


以下是Pipenv的一個示例:我正在開發一個基於Django的網站。我創建了~/git/website,並在該目錄中運行pipenv install Django。Pipenv:




  • 自動在我的主目錄中的某個位置創建一個虛擬環境。



  • 編寫一個Pip文件,它將Django列為我的依賴



  • 使用pip安裝Django



  • 繼續編寫Pipfile.lock文件,它存儲每個已安裝包(包括pytz,即Django的依賴)的確切版本和源文件碎片[2] 。


這個過程的最後一部分是最耗時的。在鎖定依賴版本的同時,Pipenv暫停了46秒鐘,這是Pipenv值得注意的問題之一:速度慢。當然,這不是唯一的一個,但它絕對沒有幫助。損失46秒並不多,但是當我們在計時測試部分中進行更長的等待時,會知道這個小問題會讓用戶覺得使用這個工具包很麻煩。

運行腳本(差勁)


但我們還是繼續吧。pipenv run django-admin startproject foobanizer 是我現在必須要用到的,它不便輸入,並且芝麻綠豆的小事都要運行pipenv。(manage.py腳本框有/usr/bin/env python。) 我可以運行pipenv shell來獲得一個新的殼,這個殼默認運行activate腳本,讓您在虛擬激活中體驗兩者中最糟糕的一個:新殼的笨拙,和造殼支持者不喜歡的激活腳本。


使用pipenv shell意味著生成一個新的子殼,執行殼啟動腳本(例如bashrc),並要求您使用Exit或^D退出,如果您鍵入 「 deactivate」,則在虛擬程序之外使用一個額外的殼。或者你可以使用—fancy模式在啟動子shell之前操縱$PATH,但是它需要一個特定的殼配置,其中$PATH在非登錄殼中不被覆蓋-還經常更改終端模擬器的配置以運行登錄殼,因為許多Linux終端不這樣做。


為什麼會發生這種事?因為一個命令不能操作它生成的殼的環境。這意味著Pipenv必須假裝它所做的是一件合理的事情,而不是一個解決辦法。這可以通過使用source$(pipenv-venv)/bin/activate(可以變成一個整潔的別名)或殼包裝器(類似於虛擬包裝器)來手動激活解決。

都完成了


不管怎樣,我想在我的網站上有個博客。我想用Markdown語法編寫它們,所以我運行pipenv install markdown,幾秒鐘後,它被添加到兩個Pipfile中。我可以做的另一件事是pipenv install-dev IPython,並獲得一個方便的殼進行修改,但它將被標記為開發依賴——因此,不會安裝在生產中。最後一部分是使用Pipenv的一個重要優勢。


當我完成我的網站工作後,我將兩個Pip文件提交到我的git存儲庫中,並將其推送到遠程伺服器。然後我可以克隆到,比如說, /srv/website。現在,我只需運行pipenv install就可以安裝所有的生產包(但不安裝開發包-Django、pytz、Markdown將被安裝,但IPython及其所有的所以依賴項都不會安裝)。只有一個警告:默認情況下,仍將在當前用戶的主目錄中創建虛擬伺服器。在本例中,這是一個問題,因為它需要由nginx和uWSGi訪問,它們無法訪問我的(或根目錄)主目錄,也沒有自己的主目錄。這可以通過導出PIPENV_VENV_IN_project=1來解決。但是請注意,每當我通過Pipenv使用/srv中的應用程序時,我都需要導出這個環境變數。該工具支持載入.env文件,但只有當運行pipenv shell和pipenv run時。你不能用它來配置Pipenv。要使用nginx或uWSGI運行我的應用程序,我需要知道精確的虛擬路徑,因為我不能將pipenv run作為uWSGI配置的一部分。

Pipenv不能做什麼


上面提到的工作流程看起來很合理,對吧?有一些不足,但除此之外,它似乎工作得很好。Pipenv的主要問題是:它在一個工作環境下運行,並且只能在一個工作環境下運行。嘗試做任何其他事情,會有很多麻煩。

Setup.py,資源分配,還有wheels文件



Pipenv只關心管理依賴關係。這不是一個包裝工具。如果你想把你的東西放在PyPI上,Pipenv派不上什麼用場。您仍然需要使用install_Requires編寫setup.py,因為Pipfile格式只指定依賴和運行時需求(Python版本),因此包名沒有位置,Pipenv不強制/期望您安裝項目。管理開發環境(作為Requiments.txt替換,或用於編寫上述文件的東西)時比較方便,但是如果您的項目有setup.py文件,則仍然需要手動管理install_Requires。Pipenv也不能自己創造wheels文件,而pip freeze 將會比Pipenv更快。

在項目駐點之外運作

Pipenv的另一個問題是使用工作目錄來選擇虛擬環境。[3]假設我是圖書館的作者。我的foobar庫的一個用戶剛剛報告了一個bug,並附上了一個repro.py文件讓我重現這個問題。我將該文件下載到我的文件系統上的~/Download目錄。用普通的舊虛擬器可以很容易地用以下語句在備用外殼中重現:



然後我可以啟動我的高級IDE來修復這個bug。我不需要在這個項目中cd。但對於Pipenv,我真的不能這麼做。如果我用命令行選項在.venv中加上虛擬,就可以鍵入~/git/foobar/.venv/bin/python~/Download/Replei.py。如果我使用集中式目錄+碎片,且還沒有儲存碎片,那麼Tab實現就變得強制性了。



如果我有兩個.py文件,或者reple.py文件,否則就依賴於在當前的工作目錄中,該怎麼辦?



這樣相當不好看。而且,使用虛擬包裝器,我可以這樣做:



別忘了Pipenv幫不了我編寫setup.py文件、分發代碼或管理釋放。它只是管理依賴,而且做得很糟糕。

Nikola


我是一個靜態站點生成器的副維護者:Nikola。作為其中的一部分,我需要在以下地方運行Nikola:




  • ~/git/nikola



  • ~/git/nikola-site



  • ~/git/nikola-plugins



  • ~/git/nikola-themes



  • ~/website (此博客)



  • /Volumes/RAMDisk/n (演示站點,用於測試,並在需要時在RAM磁碟上創建)


列表很長。Nikola的最終用戶可能沒有那麼長的列表,但他們可能有不止一個Nikola站點。對我和上述用戶來說,Pipenv不起作用。要使用Pipenv,所有這些存儲庫都需要在一個目錄中。我還需要為Nikola用戶創建一個獨立的Pipenv環境,因為這需要Django。此外,如果我們要利用項目中的文件,則Pip文件必須與~/git/Nikola連接。所以,為了讓Pipenv變得巧妙,在SSD上進行測試/bug複製(並且更快地磨損它)等…我想有一個~/Nikola目錄。我也可以直接使用虛擬環境。但是在這種情況下,Pipenv失去了它的用處,使我的工作流程更加複雜。我不能使用虛擬包裝器,因為我需要黑掉一個模糊匹配系統到它上,或者記住附加在我的虛擬名稱上的隨機字元串。這都是因為Pipenv過於依賴當前目錄。


希望使用Pipenv的Nikola最終用戶也將強制使用特定的目錄結構。如果該站點充當項目的文檔,並且在另一個項目中複製怎麼辦?兩個虛擬環境,浪費掉100兆位元組。或者更糟的是,Nikola最終進入了另一個項目的Pipfile,這在技術上對我們的下載統計數據是好的,但對其他項目的貢獻者卻不是很好。

我試著測時間的那一部分


Pipenv以速度慢而聞名。但它到底有多慢?我對它進行了測試。我使用了兩個測試環境:


遠程:DigitalMarine VPS,這是最低廉的(1 VCPU),Python 3.6/Fedora 28,在法蘭克福


本地:我的2015年買的13英寸蘋果筆記本電腦上(基本模型)Python 3.7,在一個相當慢的互聯網連接上(好的時候網速達1000萬bps,但一個測試都沒執行到)


兩者都是在2018年7月1日運行由pip安裝的Pipenv。


同時也安裝了以下cache:




  • 移除的: ~/.cache/pipenv 被移除



  • 部分: rm -rf ~/.cache/pipenv/depcache-py*.json ~/.cache/pipenv/hash-cache/



  • 不變的: 跟上一次運行沒什麼變化


事實證明Pipenv喜歡用緩存和鎖定來做一些奇怪的事情。查看活動顯示器發現,當Pipenv顯示其鎖定[包]依賴項時,網路活動正在進行…線程掛起來。沒有文件會告訴你。最糟糕的例子是在兩次運行中完成的本地Nikola安裝:第一次運行Pipenv InstallNikola在安裝軟體包後立即中斷[4],因此緩存中有所有必要的wheels文件。安裝花費了10分7秒,其中9分50秒是由鎖定依賴項和安裝鎖定的依賴項完成的-因此,大約有9分鐘半時間盯著靜態屏幕,工具在後台做一些事情-Pipenv不會告訴您這個階段會發生什麼。

(更新於2018-07-22:在Pipenv測量中:第一項是Pipenv可執行的總時間。第二項是等待Pipenv完成其「主要」任務:鎖定依賴項並安裝它們。計時在Pipenv開始鎖定依賴項時開始,在提示符出現時結束。第三項是Pipenv報告的安裝時間。因此,Pipenv安裝時間?鎖定/安裝時間?Pipfile.lock安裝時間。)



替代工具和新工具


Python打包似乎沒人會滿意。因此,有許多新的競爭者作為「最好的新包裝工具」的角色。除了Pipenv之外,還有Hatch工具(由Ofek Lev創作)和Poetry工具(由Sébastien Eustace創作)。兩者都被列為「正式」教程中的備胎選項。

Hatch?工具


Hatch工具試圖管理整個打包過程。它可以說是一種資產,因為它有助於替代其他工具。然而,也可以說,它增加了一個單一的失敗點。Hatch工具根據標準的文件例如requments.txt和setup.py來工作,因此很容易被其他文件替換。它不像Pipenv那樣搞那麼多花樣,而是更容易配置。Hatch工具所做的一些選擇是可疑的(例如手動解析pkg/_init_.py以獲取版本號,將測試套件安裝到Site-Package(相當常見的疏忽),或者它的殼特性與Pipenv一樣難看),而且它不做任何管理依賴的工作。它不一定適用於我前面提到的Django用例,也不一定適用於軟體的最終用戶。

Poetry?工具


Poetry工具介於兩者之間。它的主要目標是接近Pipenv,但也可能分配工作給PyPI。它極力隱藏它在幕後使用Pip的事實。它的自述文件附帶了一個「關於Pipenv」的延伸閱讀部分,我建議閱讀——它有更多Pipenv的不好的特性。Poetry工具聲稱使用標準化的(PEP 518)pyproject.toml文件來代替通常的大量文件。不幸的是,唯一標準化的是文件名和語法。Poetry工具使用自定義[tool.poetry]部分,這意味著人們需要Poetry工具充分使用它創建的包,這樣就離不開供應商了。(上述Hatch工具還生成一個pyproject.tmpl,其中包含元數據部分…)這裡有一個build特性來生成一個帶有setup.py以及關聯文件的sdist。


在一個簡單的Poetry工具加Nikola測試,花了24.4s/15.1 s/15.3 s來修復依賴(根據Poetry工具的計數,遠程環境,緩存移除),完成了放心輸出,沒有無聲無息的鎖定。比不上pip,但比pipenv更好。此外,代碼庫和布局是相當複雜的。Poetry工具產生工具包而不僅僅是管理依賴,所以它通常比Pipenv更有用。

Pip要留在這裡了!


但是在所有新工具的討論中,我們忘記了舊工具,它們做得很好-事實上,新工具仍然需要它們。


Pip做事又快又好。它缺乏分割生產包和開發包(如Pipenv和Poetry工具)的支持。這意味著Pip凍結和pip安裝是即時的,代價是:(A)需要兩個獨立的環境,或者(B)在生產中安裝開發依賴項(這應該是對HDD空間的浪費,而在架構良好的系統中僅此而已)。


虛擬環境管理特性可以由虛擬包裝器提供。該工具的主要優點是殼腳本實現,這意味著WorkonFoo不需要生成新的子殼就激活Foo虛擬程序(Pipenv、Hatch工具和Poetry工具中的一個問題,我在描述Pipenv操作時在「運行腳本(差勁)」一章中提過的)。Pipenv擁護者經常提出的一個論點是,創建虛擬環境無需關注自身,也不需要關心它在哪裡。不幸的是,許多工具都需要用戶擁有這種知識,或者強制指定一個特定的位置,或者要求它與主目錄不同。


對於一個具有自動發布的合理的項目模板,我有自己的叫法,稱為(偽原創的)Python項目模板(PyPT)。


是的,setup.py文件並不理想,因為它們使用.py代碼和函數執行,使得很難訪問元信息(./setup.py egg_info創建可訪問工具的文本文件)。它們的主要優點是它們是唯一被廣泛支持的格式——pip實際上是默認的Python包管理器(在windows和mac上預裝),其他工具需要先安裝/引導。

Pipenv的夭折速度


一個好的包裝工具是穩定的。換句話說,它不常變,它努力維持現有的環境。重新下載系統上的所有內容一點都不好玩,」/usr」現在被改成」/stuff」,「/usr」中的所有文件都用不了而且刪除不了。這就是Pipenv的傑作:



在一個月的時間裡,虛擬主機的位置發生了兩次變化。如果用戶沒有讀取Changelog,也沒有手動干預(同樣值得注意的是,在問題中和v3.3.4的Changelog中都提到了選項名),那麼他們就會有一個舊.venv目錄,因為他們採用了新的方案。然後,在切換到v3.5.0之後,它們將在主目錄中隱藏一個陳舊的虛擬主機,因為pipenv決定添加碎片。


而且,這是不可配置的。即使用戶想要禁用路徑中的碎片,也不能禁用。很適合那些想要混合Pipenv和虛擬包裝器的人。


Pipenv是一個非常固執己見的工具,如果開發團隊改變主意,舊的方法就不被支持了。


Pipenv更新速度很快,並且很不負責任。例如,2018-03-13:21和2018-03-14 13:44(略超過24小時)期間,Pipenv更新了10次,從11.6.2到11.7.3版本不等,完全沒通知用戶在每個版本中改變了什麼。


延伸閱讀:




  • Kenneth Reitz,致/r/python的一封信(附一些例子解釋下極度混亂的情況)



  • Reddit新聞網關於這封信的評論

結論


與流行的觀點相反,Pipenv並不是Python.org官方推薦的工具。它只是在Packaging.python.org(Pypa運行的頁面)上寫了一個關於它的教程。




  • Pipenv相當好地解決了一個用例,但在其他許多用例中失敗了,因為它強制用戶執行特定的工作。



  • Pipenv不處理任何打包過程(不能產生sidst和wheels文件)。希望上傳到PyPI的用戶需要手動管理setup.py文件,用不著Pipenv。



  • Pipenv生產鎖文件,這對複製很有用,但安裝速度較慢。速度是一個值得注意的問題,pip freeze足夠好了,即使沒有依賴類(生產和開發),也沒有碎片(這有小好處)[2]。



  • Hatch工具試圖替換許多打包工具,但一些實踐和想法是可疑的。



  • Poetry工具支持跟Pipenv一樣的缺口,同時也增加了創造包的能力,並改善了pipenv的許多不好的地方。一個值得注意的問題是使用自定義的無所不包的文件格式,這使得切換工具更加困難(供應商鎖定)。PIP、setup.py和virtualenv——傳統的、用過的真正的工具——仍然可用,並在不斷地進行開發。使用它們可以帶來更簡單、更好的體驗。同樣值得注意的是,像虛擬包裝器這樣的工具可以比前面提到的新Python工具更好地管理Virtualenv,因為它基於殼腳本(它可以修改環境)。


[1]在附帶說明中,教程什麼都沒解釋。可能有人知道它類似於NPM或Bundler(即什麼?),安裝一個包,並通過pipenv運行.py文件。


[2](1,2)請注意,上傳後不能更改PyPI上的文件,因此這隻會防止流氓PyPI管理或MitM攻擊(遇到攻擊會更麻煩)。而且,這個特點相當不好。


[3]幸運的是,它還查找Pip文件的父目錄。否則,您可能會得到foo的一個環境,foo/foo的另一個環境,foo/docs的另一個環境,等等,…


[4]由於內存磁碟空間不足而錯誤中斷,其實是件好事。

英文原文:https://chriswarrick.com/blog/2018/07/17/pipenv-promises-a-lot-delivers-very-little/


譯者:妍


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python程序員 的精彩文章:

Python金融數據分析為何這麼火???
VS Code中的Python- 2018年10月更新說明

TAG:Python程序員 |