當前位置:
首頁 > 知識 > Python包管理及構建近年來發展全景大觀

Python包管理及構建近年來發展全景大觀

Python包管理及構建近年來發展全景大觀

介紹

2018年4月16日,Python包管理局(PyPA)部署了Python項目的官方在線存儲庫PyPI(發音pie-pea-eye)的新版本。以alpha和beta形式將新版本託管在https://pypi.org上;原始URL(https://pypi.python.org/pypi)現已重定向到這個新的、更簡單的URL。

在最初被稱為Monty Python skit接著又被非正式地稱作cheese shop後,PyPI 2.0,這個名為 Warehouse的代碼,使用了在第一個版本建立時不可用的工具來構造一個更現代的體系結構。

PyPI並不是打包生態系統中唯一需要發展的部分:用於構造Python項目、構建Python發行版和安裝這些發行版的方法在過去兩到四年中已經得到了改進。對於新版本的PyPI,這裡以下是一個能促使你不斷進步的高層次的修改概覽。

  • 如果您剛接觸Python或Python中的包,我建議您首先閱讀《The Hitchhiker"s Guide to Python》和《PyPA Python Packaging User"s Guide》來了解最新的技術動態。

  • 要概觀PyPI的變化和所採取的潛在行動,從Python官方博客帖子入門是個不錯的選擇。Sumana Harihareswara關於LWN.NET的文章是對PyPI歷史和它所經歷的變化的一個很好的概述。

依賴管理器:簡化隔離和增加解析度

在2008年創建、2011發布的pip工具,在相當長的一段時間裡充當著Python事實上的安裝程序。這是一個很好的工具,但是使用PIP本身有兩個關鍵難點:

  1. 項目隔離:如果兩個不同的項目需要同一庫的兩個不同版本,開發人員如何確保項目使用正確的庫版本?

  2. 依賴同步:如果項目上的開發人員添加了新的依賴包或升級了現有的依賴包,開發人員又如何確保項目上的其他開發人員確定性地同步他們的依賴關係圖?

為了解決第一個痛點,Python開發人員曾依賴虛擬環境。最初,這包括安裝和配置virtualenv 或 virtualenvwrapper。從Python 3.3開始,Python也提供了內置的venv 模塊,為開發者提供了另一種選擇。

第二個痛點在Python世界中一直沒有得到解決。開發人員依賴於setup.py(本文稍後將討論)和指定的具有依賴項列表的 requirements.txt的約定。根據開發人員的意圖,通常建議精確(固定)或有限制(例如,Django>=2.0)地指定依賴包的版本。指定的目的是確保無論誰安裝、何時安裝都能確保安裝的一致性。然而,正確的固定或限制版本對開發人員是個複雜的手工活兒。一大主要困難來自於管理依賴包的依賴性(等等)。因此,僅使用pip確保重複安裝中依賴包版本相同是非常困難的。

PIPNEV在2017年1月首次宣布減輕雙方痛點。Pipenv充當pip和虛擬環境的包裝器,並提供了使用兩個工具解決第一個難點的無縫銜接式體驗。Pipenv通過實現依賴性解決方案和自動化行為減輕了第二個痛點。例如,Pipenv保存了正在安裝的依賴關係包的名稱和版本,以便開發人員可以放棄手動更新requirements.txt。Pipenv不依賴於requirements.txt中的依賴包列表,而是定義並創建Pipfile和Pipfile.lock文件來管理依賴包。第一個文件定義項目的直接依賴包,而第二個文件保存所有安裝的依賴包,確保安裝的一致性不受時間影響。團隊的開發人員在切換分支或從遠程拉出時仍然需要記住同步它們的依賴包,但是Pipenv將工作簡化為單個命令:pipenv sync。

Pipenv在應用程序開發中的好處導致PyPA推薦它用於應用程序的依賴管理。PyPA首先在2017年11月添加了Pipenv管理應用程序依賴包的教程,然後在2018年2月將Pipenv列為正式推薦。

顯然,PyPA推薦PiPeV用於應用程序,但不推薦用於庫。庫的依賴性需要靈活地定義,Pipenv嚴格地靠Pipfile.lock管理依賴關係,所以不適合這項任務。

Pipenv因PyPA的推薦而備受關注,但它並不是唯一的新的依賴管理器。例如,Poetry和Hatch都提供了與Pipenv重疊的功能。所有三個工具都包著PIP和VielalEnv來處理第一個痛點。然而,這是工具在它們的特徵集中開始分散的地方。

Poetry和Pipenv都致力於解決依賴性進而解決第二個痛點。值得注意的是,Poetry試圖使依賴解決方案比Pipenv的實現更可靠。更重要的是,Poetry意在同時管理應用程序和庫中的依賴包。我們將在本文後面討論這個原因。

另一個在Pipenv、Poetry和Hatch-pip工具之前的依賴管理器通過確保一致的安裝來關注第二個難點。它基於另一個文件的內容生成requirements.txt,這種文件格式可以是:requirements.in——一個由pip-tools指定的文件格式,或者其他setup.py(將在稍後討論)。它定義了用於同步環境的單個命令,使得團隊中的開發人員很容易停留在同一個頁面上,這與Pipenv非常相似。

並非所有工具在開發期間都關注代碼庫的依賴包管理;有些工具專註處理開發之外的依賴項。例如,pipsi允許將Python命令行應用程序安裝在單獨的虛擬環境中,使它們看起來是全局的,同時又將它們彼此隔離。例如,如果兩個命令行腳本需要兩個不同版本的Click,則pipsi啟用兩個工具的安裝。Jacob Kaplan Moss是Django最初的核心貢獻者之一,他在他的setup中使用Pipsi安裝Pipenv。

總之,儘管pip仍然是安裝分發包的關鍵工具,並且虛擬環境對於隔離仍然是必需的,但是許多新工具使安裝和隔離更加無縫。這些工具中的一些引入了依賴包解析,確保隨著時間推移為不同的開發人員一致地安裝依賴關係樹。Pipenv是管理應用程序依賴包的官方新工具,但它不是唯一的選擇,並且替代方案可能更契合需求。

  • 若要了解使用Pipenv的更多信息,我推薦Lacey Williams Henschel和Jeff Triplett關於這個話題的文章。

  • David Jetelina在一篇關於Pipenv的評論中闡述了Pipenv的優點和缺點。

對穩健型項目結構的新建議

  • 單個Python文件是一個模塊。一組Python文件可以成為Python程序包。

以前,開發人員如何決定在源代碼庫中組織模塊和包取決於她,並且很大程度上被視為首選。然而,對於Python庫(旨在共享的代碼)應該如何組織代碼的共識越來越多,大家都注意到了代碼組織中存在的一些陷阱。

2014年,Ionel Cristian M?rie?首先討論了使用src/目錄來保護Python代碼免受特定陷阱的影響,但反響不一。Hynek Schlawack在2016年指出,他曾無視這種方法,然後就被Lonel文中提到的問題坑了。最終,像PyTest這樣的工具現在也推薦使用這種結構,並且(正如Hynek在文章中指出的)它使得正確使用Tox進行測試更加容易。

我認為這是一個日益一致的共識,因為PyPA對於創建一個示例項目的指示明顯不遵循SRC/結構。儘管如此,該項目還是在Read Me中聲明它「不打算覆蓋整個Python項目開發的最佳實踐」。

無論如何,如果您正在啟動一個新的Python項目,或者遇到上述文章中描述的問題,基於Ionel列出的所有原因,您可能對切換項目的目錄結構感興趣。

構建Python庫的新工具

Python源代碼的生成工具的演變可能是本文討論的最重要一系列變化。這些變化需要比其他主題更仔細地觀察(打起精神,我們繼續!)

由其他包共享和安裝的Python源代碼包或捆綁包的正式稱謂叫做分發包。它們的命名可以避免混淆Python包(Python模塊的集合)的概念。

分發包可以是源碼分發包或內置分發包。如果有人正在安裝源碼分發包(例如,直接從GitHub安裝),他們的安裝程序必須在這個過程中執行構建步驟。相比之下,安裝程序可以簡單地將生成的分發包放在正確的位置。「安裝」這個術語隨便用來指代構建分發包的放置或組合的構建過程和放置。

內置的分發包有多種格式,但在此我們只關注兩種Python格式:eggs和wheels。Eggs最早可在Python 2.3中使用,但已被最早在2012年PEP 427中提出的wheels有效地替換。您可以通過閱讀PyPA打包指南或wheels包的文檔了解他們更多的差異。

如今,兩種工具使用這些格式: distutils和setuptools,來構建和分發Python代碼。

Python的distutils自2000年末與Python 2.0並行發布的Python 1.6以來,一直被用於捆綁Python代碼。2000年11月編寫的PEP 229第一次概述了使用distutils實現Python自己分發Python代碼的意圖。

setuptools項目始於2004年,構建於distutils之上,其目的是克服distutils中的限制,並包括名為easy_install的工具;setuptools是引入eggs格式的工具。Python分發遵循distutils強加的基本規則。特別是,所有Python打包和分發工具(包括pip和Pipenv)都希望源代碼分發包的根目錄中存在名為setup.py的文件。此文件描述distutils和setuptools如何從源代碼創建內置分發包。

PEP 517和PEP 518——分別在2017年9月和2016年5月被接受——通過使包的作者能夠選擇不同的構建系統,改變了這種現狀。換句話說,開發人員可選擇使用除distutils或setuptools之外的分發包構建工具,這在Python中史無前例。Python庫中無處不在的setup.py文件不再是強制性的。

正如PEP 518所描述的,開發人員現在可以在他們的代碼庫中寫一個名為pyproject.toml的TOML文件,以指定他們想要使用什麼工具來構建分發包。TOML文件可以另外配置這些構建工具,並可以為其他工具提供設置。您現在可以使用這些文件:自從PR 4144在2017年5月合併以來,pip已經知道在存儲庫和源代碼分發包中查找這些文件。

Github中關於pip的資料檔案庫提供了一個如何編寫pyproject.toml文件的例子。在這種情況下,pip定義使用setuptools和wheels構建分發包,並進一步配置Amber Brown的towncrier項目來生成新聞。然而,Python包的作者最終可以選擇用Flit或上述Poetry等工具來構建分發。沒錯:Poetry不僅僅是一個依賴性管理者,而且是一個使用pyproject.toml的分發構建者和發行者。儘管Python核心貢獻者Brett Cannon建議使用Flit,核心貢獻者Mariatta Wijaya似乎也同意這一點,但Poetry也因為它的範圍,開始引起像Jannis Leidel這樣的人的注意(Jannis Leidel是pip的原作者之一)。

我覺得離塵埃落定、這些工具找到它們的溝槽還有一段時間。值得注意的是,Flit不支持本文前面討論的src/項目結構。並且,Poetry在2018年2月才首次提交,現仍然處於pre-1.0。

總而言之,使分發包的構建更加模塊化、並允許使用新工具已是天翻地覆的變化了。

結論

Python包管理及構建近年來發展全景大觀

依賴管理器的生態系統正在迅速改善,但混亂也隨著變化出現。Pipenv、Poetry、Hatch wrap pip和虛擬環境,但他們之中沒有一個能取代pip或虛擬環境。他們之中的每一個都能提供不同的特性,解決不同的問題。正如PyPA成員Thea Flowers所指出的,沒有一個工具能滿足所有的要求。

構建工具也在快速發展,我希望我們在現有的工具成熟時的未來會看到更多。

如果你想知道使用哪些工具,首先問問自己你在努力實現什麼。您需要依賴管理器還是分發構建器?你是在編寫一個庫還是一個應用程序?你需要支持舊的設置(可能仍然需要使用setup.py)嗎,或者你的分發可以面向未來嗎?對這些問題的回答會提示你做出選擇。我發現自己唯一具有規定性的地方是使用src/項目結構,因為它避免了隱含的錯誤,並使得項目中新手開發人員的生活更容易——但即便如此,也不是每個人都認同這點。

打包Python長期以來一直是語言和社區的痛點(參見2013年Nick Coghlan關於用Python進行打包的說明)。上述變化是喜聞樂見的,我們在此誠摯地感謝辛勤工作對此做出貢獻的個人。請花點時間在Twitter、Github上或親自感謝他們吧!

  • Dustin Ingram是本文的審稿人之一。在PyCon US 2018上,他就此話題發表了演講。你可以在YouTube上看到他精彩的演講。

  • 這裡所涉及的主題只是過去和現在所有工作中的一小部分。PyPA"s history of Python packaging 提供了一個自1998以來的變化列表,這是一個引人入勝的回顧。

原文撰稿人: Andrew Pinkham

原文校對人: Dustin Ingram, Jeff Triplett

原文文字編輯: Holly Monteith

原文美編: Emilia Jesenska


英文原文:http://andrewsforge.com/article/python-new-package-landscape/
譯者:盈韜

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

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


請您繼續閱讀更多來自 Python部落 的精彩文章:

TAG:Python部落 |