該和virtualenv說再見嗎?

该和virtualenv说再见吗?

如果你是一個Python開發人員,你可能聽說過Virtual Environments。Virtual Environments是“一個自包含的目錄樹,其中包含特定版本的Python安裝環境,以及一些額外的包”。

它們為什麼這麼受歡迎?因為,它們解決了一個問題:不需要再將所有包都安裝到全局site-packages組成的大雜燴中。相反,每個項目可以在它們自己的“虛擬”環境中安裝精確的依賴項版本。

然而,它們也帶來了一些問題:

  • 學習曲線:向那些只想進入虛擬環境並編寫代碼的人解釋“虛擬環境”並不總是那麼容易

  • 終端隔離:Virtual Environments的激活和停用基於每個終端

  • 認知開銷:設置、記住安裝位置、激活/停用

為了解決上述問題,我們創造了新的高級工具,如pipenv、poetry、flit和hatch。這些工具通過隱藏pip和Virtual Environments的複雜性來改善這種情況。然而,為了隱藏複雜性,它們本身又變得比較複雜。它們也有自己的API、學習曲線和維護負擔。

走進PEP 582 ——Python本地包目錄

早在2018年5月,就引入了一個Python增強提案(PEP)來修改Python本身以解決由虛擬環境解決的許多問題,但採用了一種完全不同且比較簡單的方法。請注意,該PEP仍然處於草案狀態,因此它可能仍然會更改,或者甚至可能根本不會被採納。

我們來看一下PEP 582[1]中的一段話:

本PEP提案向Python中添加一種機制來自動識別__pypackages__目錄,並且優先導入安裝在該位置的包,而不是用戶或全局site-packages。這將避免創建、激活或停用“虛擬環境”的步驟。Python將使用腳本所在根目錄中的__pypackages__,如果這個目錄存在的話。

本提案通過搜索本地路徑來尋找額外的包,從而有效地解決了Virtual Environments及其高級副本的所有複雜性。

現在就嘗試一下

它甚至附帶了一個參考CPython實現[2]。

如果你沒有時間或者沒有興趣構建一個CPython二進制文件,那麼可以嘗試我創建的Python包裝器的概念驗證,稱為pythonloc[3](指代“Python local”)。這是一個Python包(少於100行代碼),它完成了PEP 582所描述的工作。

pythonloc運行Python,但會從__pypackages__中導入包(如果存在的話)。它還附帶piploc, piploc與pip相同,只不過piploc是安裝/卸載到__pypackages__。

這裡有一個例子。

该和virtualenv说再见吗?

注意:這可能與你在site packages目錄中找到的內容相同,比如~/.local/lib/python3.6/site-packages。

如你所見,piploc將requests包安裝到了__pypackages__/3.6/lib/requests。運行python表明它沒有找到requests 包(這是意料之中的,因為它沒有搜索__pypackages__目錄)。

要讓Python找到它,你可以運行pythonloc,這與運行PYTHONPATH=.:__pypackages__:$PYTHONPATH python是相同的。這樣程序運行是就會搜索__pypackages__目錄並找到requests安裝。

現在,你可以通過運行以下代碼來嘗試pythonloc:

该和virtualenv说再见吗?

你可以訪問https://github.com/cs01/pythonloc 來學習更多。

安裝多個依賴項或鎖文件

如果你有可用的源代碼,並且它有一個setup.py文件,你可以運行

该和virtualenv说再见吗?

然後運行pythonloc並使所有依賴項可用。

如果你有一個requirements.txt文件,你可以運行

该和virtualenv说再见吗?

如果你正在使用pipenv,那麼你可以通過以下代碼生成一個requirements.txt文件

该和virtualenv说再见吗?

最後,如果你正在使用poetry,那麼你可以使用以下代碼生成requirements.txt文件

该和virtualenv说再见吗?

凍結依賴性

雖然我們可以從各種源來安裝依賴項,但如果我們正在開發並想要生成一個依賴項列表呢。

隨著__pypackages__的出現,你可以使用一種新的工作流來創建依賴項列表,並將__pypackages__本身提交到源代碼控制中。這樣做實際上可以保證你使用的是相同的版本,因為你使用的是完全相同的源代碼。

假設你不想這樣做,那麼可以運行piploc freeze。但這帶來了一個問題。它顯示了所有已安裝的python包: site-packages中的包以及__pypackages__中的包。這可能不是你想要的,因為它包含的內容比你安裝到__pypackages__的內容要多。

你可能只想輸出安裝到__pypackages__中的包。這正是pipfreezeloc所做的。

该和virtualenv说再见吗?

它相當於pip freeze,但只輸出__pypackages__中的包。這是必需的,因為在pip中沒有內置的方法來實現這一點。例如,命令pip freeze --target __pypackages__並不存在。

因此代替運行

该和virtualenv说再见吗?

你可以運行

该和virtualenv说再见吗?

結 論

PEP 582是一個提案草案,它引入了一種新的方法來在沒有Virtual Environments的情況下安裝和隔離包。它還消除了項目位置和環境位置之間的間接關係,因為安裝位置始終與項目位置在相同的目錄中——在__pypackages__中。

pythonloc(和piploc, pipfreezeloc)是目前可用的PEP 582 Python實現的一個概念驗證。

你怎麼認為?PEP 582是否應該被批准(請注意,在此過程中我不是決策者,只是一個感興趣的觀察者)? Virtual Environments的依賴性會降低嗎?pythonloc改善了你的工作流程嗎?

相關連接:

[1]——https://www.python.org/dev/peps/pep-0582/

[2]——https://github.com/kushaldas/cpython/tree/pypackages

[3]——https://github.com/cs01/pythonloc

英文原文:https://qiniumedia.freelycode.com/vcdn/1/%E4%BC%98%E8%B4%A8%E6%96%87%E7%AB%A0%E9%95%BF%E5%9B%BE3/goodbyevirtualenvironments.pdf
譯者:一瞬


分享到:


相關文章: