簡體   English   中英

requirements.txt 與 setup.py

[英]requirements.txt vs setup.py

我開始使用 Python。 我已將requirements.txtsetup.py添加到我的項目中。 但是,我仍然對這兩個文件的用途感到困惑。 我讀過setup.py是為可再分發的東西設計的,而requirements.txt是為不可再分發的東西設計的。 但我不確定這是准確的。

這兩個文件真正打算如何使用?

requirements.txt

這有助於您設置開發環境。

pip等程序可用於一次性安裝文件中列出的所有軟件包。 之后你就可以開始開發你的 python 腳本了。 如果您計划讓其他人參與開發或使用虛擬環境,這將特別有用。 這是你如何使用它:

pip install -r requirements.txt

它可以通過pip本身輕松生成:

pip freeze > requirements.txt

pip自動嘗試僅添加默認情況下未安裝的包,因此生成的文件非常小。


setup.py

這有助於您創建可以重新分發的包。

setup.py腳本用於在最終用戶的系統上安裝您的包,而不是像pip install -r requirements.txt那樣准備開發環境。 有關setup.py的更多詳細信息,請參閱此答案


您的項目的依賴項列在兩個文件中。

簡短的回答是requirements.txt僅用於列出包需求。 另一方面, setup.py更像是一個安裝腳本。 如果您不打算安裝 python 代碼,通常您只需要requirements.txt

文件setup.py除了包依賴性之外,還描述了應該打包(或編譯,在本機模塊(即用 C 編寫)的情況下)的文件和模塊集,以及要添加到 python 的元數據包列表(例如包名、包版本、包描述、作者……)。

因為這兩個文件都列出了依賴項,所以這可能會導致一些重復。 閱讀下文了解詳情。

要求.txt


此文件列出了 python 包要求。 它是一個純文本文件(可選地帶有注釋),其中列出了您的 Python 項目的包依賴項(每行一個)。 沒有描述安裝 python 包的方式。 您通常會使用pip install -r requirements.txt使用需求文件。

文本文件的文件名是任意的,但通常按照約定為requirements.txt 在探索其他 python 包的源代碼存儲庫時,您可能會偶然發現其他名稱,例如dev-dependencies.txtdependencies-dev.txt 這些與dependencies.txt的目的相同,但通常會列出特定包的開發人員感興趣的其他依賴項,即用於在發布前測試源代碼(例如 pytest、pylint 等)。 包的用戶通常不需要整套開發人員依賴項來運行包。

如果存在多個requirements-X.txt變體,那么通常一個會列出運行時依賴項,另一個會列出構建時或測試依賴項。 一些項目還級聯它們的需求文件,即當一個需求文件包含另一個文件時(示例)。 這樣做可以減少重復。

安裝程序.py


這是一個 python 腳本,它使用setuptools模塊來定義 python 包(名稱、包含的文件、包元數據和安裝)。 requirements.txt一樣,它也會列出包的運行時依賴項。 Setuptools 是構建和安裝 python 包的實際方式,但它有其缺點,隨着時間的推移,它催生了新的“元包管理器”的開發,如 pip。 setuptools 的示例缺點是它無法安裝同一包的多個版本,並且缺少卸載命令。

當 python 用戶執行pip install./pkgdir_my_module (或pip install my-module )時,pip 將在給定目錄(或模塊)中運行setup.py 類似地,任何具有setup.py的模塊都可以通過pip安裝,例如通過運行pip install. 來自同一個文件夾。

我真的需要兩者嗎?


簡短的回答是否定的,但兩者都很好。 它們實現不同的目的,但它們都可以用來列出您的依賴項。

您可以考慮一種技巧來避免重復requirements.txtsetup.py之間的依賴項列表。 如果您已經為您的包編寫了一個完全可用的setup.py ,並且您的依賴項主要是外部的,您可以考慮只包含以下內容的簡單requirements.txt

 # requirements.txt
 #
 # installs dependencies from ./setup.py, and the package itself,
 # in editable mode
 -e .

 # (the -e above is optional). you could also just install the package
 # normally with just the line below (after uncommenting)
 # .

-e是一個特殊的pip install選項,它以可編輯模式安裝給定的包。 pip -r requirements.txt在此文件上運行時,pip 將通過./setup.py中的列表安裝您的依賴項。 editable 選項將在您的安裝目錄中放置一個符號鏈接(而不是 egg 或存檔副本)。 它允許開發人員從存儲庫中就地編輯代碼而無需重新安裝。

當您的軟件包存儲庫中有這兩個文件時,您還可以利用所謂的“setuptools extras”。 您可以在自定義類別下的 setup.py 中定義可選包,並使用 pip 從該類別安裝這些包:

# setup.py
from setuptools import setup
setup(
   name="FOO"
   ...
   extras_require = {
       'dev': ['pylint'],
       'build': ['requests']
   }
   ...
)

然后,在需求文件中:

# install packages in the [build] category, from setup.py
# (path/to/mypkg is the directory where setup.py is)
-e path/to/mypkg[build]

這會將您所有的依賴項列表保存在 setup.py 中。

注意:您通常會從沙箱中執行 pip 和 setup.py,例如使用程序virtualenv創建的沙箱。 這將避免在項目開發環境的上下文之外安裝 python 包。

為了完整起見,這里是我從3 4 個不同角度看待它的方式。

  1. 他們的設計目的不同

這是官方文檔中引用的精確描述(重點是我的):

而 install_requires(在 setup.py 中)定義了單個項目的依賴項,而 Requirements 文件通常用於定義完整 Python 環境的要求。

盡管 install_requires 要求很少,但要求文件通常包含詳盡的固定版本列表,以實現完整環境的可重復安裝。

但它可能仍然不容易理解,所以在下一節中,有 2 個實際示例來演示這兩種方法應該如何不同地使用。

  1. 因此,它們的實際用法(應該)不同
  • 如果你的項目foo將作為一個獨立的庫發布(也就是說,其他人可能會做import foo ),那么你(和你的下游用戶)會希望有一個靈活的依賴聲明,這樣你的庫就不會(和它不能)對您的依賴項的確切版本應該是“挑剔的”。 因此,通常,您的 setup.py 將包含如下行:

     install_requires=[ 'A>=1,<2', 'B>=2' ]
  • 如果您只是想以某種方式“記錄”或“固定”您應用程序bar的確切當前環境,這意味着您或您的用戶希望按原樣使用您的應用程序bar ,即運行python bar.py ,您可能需要凍結您的環境,使其始終表現相同。 在這種情況下,您的需求文件將如下所示:

     A==1.2.3 B==2.3.4 # It could even contain some dependencies NOT strickly required by your library pylint==3.4.5
  1. 實際上,我使用哪一個?

    • 如果您正在開發將由python bar.py使用的應用程序bar ,即使那是“只是為了好玩的腳本”,仍然建議您使用 requirements.txt 因為,誰知道,下周(恰好是聖誕節) 你會收到一台新電腦作為禮物,所以你需要在那里重新設置你的確切環境。

    • 如果您正在開發將由import foo使用的庫foo ,則必須准備一個 setup.py。 時期。 但是你仍然可以選擇同時提供一個 requirements.txt,它可以:

      (a) 要么采用A==1.2.3風格(如上文#2 所述);

      (b) 或者只包含一個神奇的單曲.

       .

      后者本質上是使用常規的requirements.txt習慣來記錄你的安裝步驟是pip install. ,意思是“根據setup.py安裝需求”,同時不重復。 我個人認為最后一種方法有點模糊了界限,增加了混亂,但它仍然是一種在 CI 環境中運行時明確選擇退出依賴固定的便捷方法。 這個技巧源自 Python 打包維護者 Donald 在他的博客文章中提到的一種方法。

  2. 不同的下界。

    假設有一個具有此歷史記錄的現有engine庫:

     engine 1.1.0 Use steam... engine 1.2.0 Internal combustion is invented engine 1.2.1 Fix engine leaking oil engine 1.2.2 Fix engine overheat engine 1.2.3 Fix occasional engine stalling engine 2.0.0 Introducing nuclear reactor

    您遵循上述 3 個標准並正確地決定您的新庫hybrid-engine將使用setup.py來聲明其依賴項engine>=1.2.0,<2 ,然后您的分離應用程序reliable-car將使用requirements.txt來聲明其依賴engine>=1.2.3,<2 (或者您可能只想固定engine==1.2.3 )。 如您所見,您對它們的下限數字的選擇仍然略有不同,並且它們都沒有使用最新的engine==2.0.0 這就是為什么。

    • hybrid-engine依賴於engine>=1.2.0因為,所需的add_fuel() API 是在engine 1.2.0中首次引入的,並且該功能是hybrid-engine的必要性,無論是否存在一些(小)錯誤在此類版本中,並在后續版本 1.2.1、1.2.2 和 1.2.3 中得到修復。

    • reliable-car依賴於engine>=1.2.3因為這是迄今為止沒有已知問題的最早版本。 當然在以后的版本中有新功能,即engine 2.0.0中引入的“核反應堆”,但它們不一定是項目reliable-car所需要的。 (您的另一個新項目time-machine可能會使用engine>=2.0.0 ,但這是另一個主題。)

長話短說

  • requirements.txt列出了具體的依賴關系
  • setup.py列出抽象依賴

對於 Python 中的依賴管理,一個常見的誤解是您是否需要使用requirements.txtsetup.py文件來處理依賴。

您可能必須同時使用兩者,以確保在您的 Python 項目中正確處理依賴項。

requirements.txt文件應該列出具體的依賴關系 換句話說,它應該列出固定的依賴項(使用==說明符)。 然后將使用此文件來創建一個工作的虛擬環境,該環境將安裝所有依賴項,並具有指定的版本。

另一方面, setup.py文件應該列出抽象依賴項。 這意味着它應該列出運行項目的最小依賴項。 除了依賴管理之外,這個文件還服務於包分發(比如在 PyPI 上)。

如需更全面的閱讀,您可以閱讀文章requirements.txt vs setup.py in Python on TDS。


現在,從 PEP-517 和 PEP-518 開始,您可能必須使用pyproject.toml來指定您要使用setuptools作為構建工具,並使用額外的setup.cfg文件來指定詳細信息。 有關詳細信息,您可以閱讀文章setup.py vs setup.cfg in Python

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM