Python 依賴管理的迷宮

2022年09月14日11:15:02 科技 1187

在這篇文章中,我想對 Python 中的依賴管理有所了解。Python 依賴管理是一個完全不同的世界。

Python 依賴管理的迷宮 - 天天要聞

20 多年來,我一直在為 JVM 開發代碼,首先是 Java,然後是 Kotlin。但是,JVM 並不是靈丹妙藥,例如,在腳本中:

  1. 虛擬機需要額外的內存
  2. 在許多情況下,腳本運行的時間不夠長,無法在性能方面獲得任何好處。位元組碼被解釋並且永遠不會編譯為本機代碼。

由於這些原因,我現在用 Python 編寫腳本。其中之一從不同來源收集社交媒體指標並將其存儲在 BigQuery 中以供分析。

我不是 Python 開發人員,但我正在學習 - 很難。在這篇文章中,我想對 Python 中的依賴管理有所了解。

Python 中足夠的依賴管理

在 JVM 上,依賴管理似乎是一個已解決的問題。首先,您選擇您的構建工具,最好是 Maven 或另一種我不應該命名的工具。然後,您聲明您的直接依賴關係,並且該工具管理間接依賴關係。這並不意味著沒有陷阱,但您可以或多或少地快速解決它們。

Python 依賴管理是一個完全不同的世界。首先,在 Python 中,運行時及其依賴項是系統範圍的。一個系統只有一個運行時,並且依賴項在該系統上的所有項目之間共享。因為不可行,所以開始一個新項目的第一件事就是創建一個虛擬環境。

這個問題的解決方案是創建一個虛擬環境,一個自包含的目錄樹,其中包含特定版本的 Python 的 Python 安裝,以及一些額外的包。

然後不同的應用程序可以使用不同的虛擬環境。為了解決前面的衝突需求示例,應用程序 A 可以擁有自己的安裝了 1.0 版的虛擬環境,而應用程序 B 擁有另一個安裝了 2.0 版的虛擬環境。如果應用程序 B 需要將庫升級到版本 3.0,這不會影響應用程序 A 的環境。

--虛擬環境和包

一旦完成,事情就會認真開始。

pipPython 提供了一個開箱即用的依賴管理工具:

您可以使用名為 pip 的程序安裝、升級和刪除軟體包。

--使用 pip 管理包

工作流程如下:

  1. 在虛擬環境中安裝所需的依賴項:pip install flask
  2. 在安裝了所有必需的依賴項後,將它們保存在requirements.txt按約定命名的文件中:pip freeze > requirements.txt

    該文件應與常規代碼一起保存在一個人的VCS中。

  3. pip其他項目開發人員可以通過指向安裝相同的依賴項requirements.txt:pip install -r requirements.txt

以下是requirements.txt上述命令的結果:

click==8.1.3
Flask==2.2.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
Werkzeug==2.2.2

依賴和傳遞依賴

在描述這個問題之前,我們需要解釋一下什麼是傳遞依賴。傳遞依賴項是項目不直接需要的依賴項,而是項目的依賴項之一或依賴項的依賴項一直需要的依賴項。在上面的示例中,我添加了flask依賴項,但pip總共安裝了 6 個依賴項。

我們可以安裝deptree依賴來檢查依賴樹。

pip install deptree

輸出如下:

Flask==2.2.2 # flask
Werkzeug==2.2.2 # Werkzeug>=2.2.2
MarkupSafe==2.1.1 # MarkupSafe>=2.1.1
Jinja2==3.1.2 # Jinja2>=3.0
MarkupSafe==2.1.1 # MarkupSafe>=2.0
itsdangerous==2.1.2 # itsdangerous>=2.0
click==8.1.3 # click>=8.0

# deptree and pip trees

它的內容如下:Flaskrequires Werkzeug,這反過來又需要MarkupSafe。Werkzeug並MarkupSafe有資格作為我的項目的傳遞依賴項。

版本部分也很有趣。第一部分提到安裝的版本,而注釋部分是指兼容的版本範圍。例如Jinja需要版本3.0或以上,安裝的版本為3.1.2.

安裝的版本是安裝時找到的最新兼容pip版本。pip並deptree了解setup.py沿每個庫分發的文件的兼容性:

安裝腳本是使用 Distutils 構建、分發和安裝模塊的所有活動的中心。設置腳本的主要目的是向 Distutils 描述您的模塊分發,以便對您的模塊進行操作的各種命令執行正確的操作。

--編寫安裝腳本

flask在這裡:

from setuptools import setup

setup(
name="Flask",
install_requires=[
"Werkzeug >= 2.2.2",
"Jinja2 >= 3.0",
"itsdangerous >= 2.0",
"click >= 8.0",
"importlib-metadata >= 3.6.0; python_version < '3.10'",
],
extras_require={
"async": ["asgiref >= 3.2"],
"dotenv": ["python-dotenv"],
},
)

點和傳遞依賴

出現問題是因為我希望我的依賴項是最新的。為此,我已將 Dependabot 配置為監視requirements.txt. 當這樣的事件發生時,它會在我的 repo 中打開一個PR 。大多數時候,PR 就像一個魅力,但在少數情況下,當我在合併後運行腳本時會發生錯誤。它如下所示:

純文本1錯誤:libfoo 1.0.0 要求 libbar<2.5,>=2.0,但您將擁有不兼容的 libbar 2.5。

問題是 Dependabot 為列出的每個庫打開一個 PR。但是可以發布一個新的庫版本,這超出了兼容性的範圍。

想像一下下面的情況。我的項目需要libfoo依賴。反過來,libfoo需要libbar依賴。在安裝時,pip使用最新版本libfoo和最新兼容版本的libbar. 結果requirements.txt是:

純文本1libfoo==1.0.02庫==2.0

一切都按預期工作。過了一會兒,Dependabot 運行並發現libbar已經發布了一個新版本,例如2.5. 忠實地,它打開了一個 PR 來合併以下更改:

純文本1libfoo==1.0.02庫==2.5

是否出現上述問題僅取決於如何libfoo 1.0.0在setup.py. 如果2.5在兼容範圍內,則有效;如果沒有,它不會。

pip-compile拯救

問題pip在於它列出了傳遞依賴和直接依賴。Dependabot 然後獲取所有依賴項的最新版本,但不驗證傳遞依賴項版本更新是否在該範圍內。它可能會檢查,但requirements.txt文件格式不是結構化的:它不區分直接依賴和傳遞依賴。顯而易見的解決方案是僅列出直接依賴項。

好消息是pip只允許列出直接依賴項;它自動安裝傳遞依賴。壞消息是我們現在有兩個requirements.txt選項無法區分它們:一些僅列出直接依賴關係,而另一些則列出所有依賴關係。

它需要一個替代方案。pip-tools有一個:

  1. 一個在一個文件中列出了它們的直接依賴關係,該requirements.in文件的格式與requirements.txt
  2. 該pip-compile工具requirements.txt從requirements.in.

例如,給定我們的 Flask 示例:

#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile requirements.in
#
click==8.1.3
# via flask
flask==2.2.2
# via -r requirements.in
itsdangerous==2.1.2
# via flask
jinja2==3.1.2
# via flask
markupsafe==2.1.1
# via
# jinja2
# werkzeug
werkzeug==2.2.2
# via flask

pip install -r requirements.txt

它具有以下好處和後果:

  • 生成的requirements.txt包含注釋以了解依賴關係樹
  • 由於pip-compile生成文件,您不應將其保存在 VCS 中
  • 該項目與依賴於的遺留工具兼容requirements.txt
  • 最後但同樣重要的是,它改變了安裝工作流程。不是安裝包然後保存它們,而是首先列出包然後安裝它們。

此外,Dependabot 可以管理pip-compile.

結論

這篇文章描述了默認 Python 的依賴管理系統以及它如何破壞自動版本升級。我們繼續描述pip-compile解決問題的替代方案。

請注意,Python 存在依賴管理規範,PEP 621 – 在 pyproject.toml 中存儲項目元數據。它類似於 Maven 的 POM,但格式不同。這在我的腳本上下文中是多餘的,因為我不需要分發項目。但是你應該這樣做,知道它pip-compile是兼容的。


科技分類資訊推薦

交直流兩用電子管收音機 - 天天要聞

交直流兩用電子管收音機

交直流兩用收音機這是《無線電》雜誌1966年第2期P19上的一篇,介紹如何製作一台既能使用直流電源、還能使用交流電源的電子管三燈收音機。交直流兩用收音機:舊時光里的聲音魔法在電子設備日新月異的今天,回望過去,這台交直流兩用收音機,滿是歲月韻
【智能化】小馬智行第七代Robotaxi廣深開跑 - 天天要聞

【智能化】小馬智行第七代Robotaxi廣深開跑

近日,從小馬智行官方處獲悉,其第七代自動駕駛系統的廣汽埃安霸王龍自動駕駛車輛,正式獲得智能網聯汽車道路測試牌照,在廣州和深圳開啟公開道路測試。這意味著小馬智行第七代自動駕駛車輛在完成實驗室與封閉場地的驗證後,正式進入真實交通環境開展測試,為量產和商業化進程按下加速鍵。此前,在今年上海車展上,小馬智行...
車圈大佬,集體開撕;周鴻禕:準備幹掉360整個市場部;河南首富換人!85後身家超1400億;王自如直播,「絕不帶貨」|| 大件事 - 天天要聞

車圈大佬,集體開撕;周鴻禕:準備幹掉360整個市場部;河南首富換人!85後身家超1400億;王自如直播,「絕不帶貨」|| 大件事

wumiancaijing.com////最熱的泛財經新聞,都在這兒了。重要提醒!!!為防失聯,請「星標」我們!進入無冕財經公眾號,點擊右上角「...」,再「設為星標」,以便您及時接收每篇推送~本文由無冕財經(wumiancaijing)整理髮布資訊整理:海棠葉編輯:程程設計:嵐昇比亞迪回應「常壓油箱」、「車圈恆大」王傳福哽咽:比亞迪是...
上觀伴考季分秒贏好禮 - 天天要聞

上觀伴考季分秒贏好禮

6月6日、6月7日、6月8日「上觀伴考季,分秒贏好禮」活動獲獎結果已經出爐。以下為每日分享用戶中隨機抽取的5名幸運用戶,以及每日(0點-24點)在App內在線時長排名前30名的用戶。獎品分別為價值200元的上觀新聞周邊禮盒、50元話費充值卡
廣州赤兔商務信息:商務領域的智慧領航者 - 天天要聞

廣州赤兔商務信息:商務領域的智慧領航者

在廣州這座充滿活力與機遇的商業之都,廣州赤兔商務信息有限公司宛如一匹矯健的赤兔馬,以其敏銳的商業洞察力、專業的服務能力和高效的執行效率,在商務信息服務領域一路馳騁,成為眾多企業信賴的合作夥伴。公司擁有一支由資深市場分析師、行業專家和數據挖掘高手組成的專業團隊,他們憑藉豐富的經驗和深厚的專業知識,深入...
輔信推出 XPC nano NE10N 迷你電腦,搭載英特爾 N100 處理器 - 天天要聞

輔信推出 XPC nano NE10N 迷你電腦,搭載英特爾 N100 處理器

IT之家 6 月 9 日消息,輔信 Shuttle 推出新款迷你主機 XPC nano NE10N,搭載英特爾 N100 處理器,支持壁掛和連接最多兩台 4K / 60Hz 顯示器。XPC nano NE10N 尺寸為 135×115×41.3mm,提供准系統版本(不含內存與硬碟),配備單個 SO-DIMM 插槽,最高支持 16GB DDR4-3200 內存
魅族 PANDAER 聯名聯想拯救者 Y9000P 至尊版 / R9000P 上架 - 天天要聞

魅族 PANDAER 聯名聯想拯救者 Y9000P 至尊版 / R9000P 上架

IT之家 6 月 9 日消息,魅族 PANDAER 與聯想合作推出的拯救者 Y9000P 至尊版 / R9000P AI 元啟白金獨角獸限定電競本現已上架魅族商城,可以看作是系列筆記本入門 / 中配款型換上「靈龍限定塗裝」,IT之家整理具體價格如下:Y9000P 至尊版(Ultra 9 275HX + 32GB RAM + 1TB + RTX 5070Ti)
GPD MicroPC 2 官宣:單核性能秒一代 MicroPC,凈重 490 克 - 天天要聞

GPD MicroPC 2 官宣:單核性能秒一代 MicroPC,凈重 490 克

IT之家 6 月 9 日消息,GPD 曾在 2019 年推出 MicroPC 產品,後續在 2021 年將 N4100 處理器更新到 N4120,已經有 6 年沒有真正的迭代產品發布。GPD 官方今日宣布,即將推出 MicroPC 2,繼承了上一代的小巧便攜低功耗的設計,屏幕由 6 英寸提升到 7 英寸,但整機僅比一代重約 50 克,凈重 490 克。▲ 左