requirements.txt проти setup.py


111

Я почав працювати з Python. Я додав requirements.txtі setup.pyдо свого проекту. Але мене все ще бентежить призначення обох файлів. Я читав, що setup.pyпризначений для речей, що розподіляються, і що requirements.txtпризначений для речей, що не розподіляються. Але я не впевнений, що це точно.

Як ці два файли справді призначені для використання?


1
Ви шукали в Інтернеті, використовуючи свою точну назву? Ця стаття (перша хіт, коли я шукав) - найкраща, яку я прочитав на цю тему.
Кріс,

2
Ця стаття може бути корисною: caremad.io/posts/2013/07/setup-vs-requirement (вибачте, лінуєтесь витягнути необхідне у правильну відповідь). Інша справа, що деякі інструменти (наприклад, тестування) можуть мати упереджене ставлення до того чи іншого - але нехай це вас не турбує, якщо ви щойно почали працювати над Python.
drdaeman

Відповіді:


83

вимоги.txt

Це допомагає налаштувати середовище для розробки. Такі програми pipможна використовувати для встановлення всіх пакунків, перелічених у файлі, одним махом. Після цього ви можете розпочати розробку вашого сценарію python. Особливо корисно, якщо ви плануєте, щоб інші сприяли розробці або використовували віртуальне середовище. Ось як ви ним користуєтесь:

pip install -r requirements.txt

setup.py

Це дозволяє створювати пакунки, які можна перерозподіляти. Цей скрипт призначений для встановлення вашого пакету в системі кінцевого користувача, а не для підготовки середовища розробки, як pip install -r requirements.txtце робиться. Дивіться цю відповідь, щоб отримати докладнішу інформацію про setup.py.

Залежності вашого проекту вказані в обох файлах.


2
В яких випадках я мав би лише один із них? У якому б я мав обидва?
Мартін Тома,

27
Е-м-м-м ... Ви просто сценарій для розваги на своїй локальній машині: Ні. Сценарій розробляється на декількох машинах / vitualenvs, але не перерозподіляється: requirements.txt. Сценарій розробляється лише на вашому комп'ютері, але його слід розповсюджувати: setup.py. Скрипт буде перерозподілятися та розроблятися в різних середовищах: обидва.
AndreasT

Не могли б ви додати це до відповіді?
Мартін Тома

58

Коротка відповідь полягає в тому, що 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.txtабо dependencies-dev.txt. Вони слугують тій самій меті, що dependencies.txtі загалом перелічують додаткові залежності, що цікавлять розробників певного пакету, а саме для тестування вихідного коду (наприклад, pytest, pylint тощо) перед випуском. Користувачам пакету, як правило, не знадобиться весь набір залежностей розробника для запуску пакета.

Якщо requirements-X.txtприсутні кілька варіантів, то, як правило, в одному буде вказано залежності часу виконання, а в іншому - час побудови або тестові залежності. Деякі проекти також каскадують файл своїх вимог, тобто коли один файл вимог включає інший файл ( приклад ). Це може зменшити повторення.

setup.py


Це сценарій python, який використовує setuptoolsмодуль для визначення пакета python (ім’я, включені файли, метадані пакета та встановлення). Він також, як requirements.txt, також перелічить залежності виконання пакунка. Setuptools - це фактичний спосіб створення та встановлення пакетів python, але він має свої недоліки, які з часом породили розробку нових "менеджерів мета-пакетів", таких як pip. Прикладом недоліків setuptools є його неможливість встановити кілька версій одного пакета та відсутність команди видалення.

Коли користувач python робить pip install ./pkgdir_my_module(або pip install my-module), pip буде виконуватися setup.pyу вказаному каталозі (або модулі). Подібним чином, будь-який модуль, який має a, setup.pyможе бути pipвстановлений, наприклад, запуском pip install .з тієї ж папки.

Мені справді потрібні обидва?


Коротка відповідь - ні, але приємно мати обидва. Вони досягають різних цілей, але їх обох можна використовувати для переліку ваших залежностей.

Існує одна хитрість, яку ви можете розглянути, щоб уникнути дублювання списку залежностей між requirements.txtта setup.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. Параметр, який можна редагувати, розмістить символічне посилання у вашому каталозі встановлення (замість яйця або заархівованої копії). Це дозволяє розробникам редагувати код на місці зі сховища без перевстановлення.

Ви також можете скористатися тим, що називається "додатками setuptools", коли у вашому сховищі пакетів є обидва файли. Ви можете визначити додаткові пакети в 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 поза контекстом середовища розробки вашого проекту.


7
і ви також можете мати тільки .ж / о -eвнутрішньої requirements.txt. Цей метод просто делегує всі вимоги, setup.pyі вам не потрібно примушувати когось переходити в режим редагування. Користувачі все ще можуть робити, pip install -e .якщо хочуть.
stason

1
Цікавий фокус із "-е". в requirements.txt, але чи не перешкоджає це цілі requirements.txt, будучи точними специфікаціями системи? Навіщо взагалі такий у такому разі?
Бен Огорек,

Ви можете мати точні системні вимоги всередині setup.py. Маючи "." in requirements.txt змушує використовувати setup.py у поточній папці. Використання -e .також використовує setup.py для пошуку залежностей, але пов'язує поточну папку (на місці, із символічним посиланням) у папці pip install, а не робить копію - ви -eзазвичай використовуєте лише у випадку, коли розробляєте пакет. З -e, зміни в файли пітон пакет (* .py) вступить в силу негайно у вашому середовищі пипа, замість того , щоб силою повторно встановити пакет після кожної зміни.
init_js

@init_js - це "поточна папка" щодо файлу вимог або CWD, з якого викликається pip? Тобто, якщо ви це зробите cd foo && pip install -r ./bar/requirements.txt, він буде шукати файл setup.py в foo/barабо foo? Якщо останнє, чи є спосіб досягти першого?
Ден М.

pip -r REQне хвилює каталог, в якому знаходиться REQ. Ви можете годувати його з ФІФО , навіть якщо ви хочете: pip install -r <(echo "mylib1"; echo "mylib2";). Де <(CMD)є заміна команди bash, а не перенаправлення stdin.
init_js

12

Для повноти, ось як я бачу це в 3 4 різних кутах.

  1. Їх цілі дизайну різні

Ось точний опис, наведений в офіційній документації (наголос на моєму):

Тоді як install_requires (у setup.py) визначає залежності для одного проекту , Файли вимог часто використовуються для визначення вимог до повного середовища 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
  2. Насправді, який із них я використовую?

    • Якщо ви розробляєте програму, barякою користуватиметься python bar.py, навіть якщо це "просто сценарій для розваги", вам все одно рекомендується використовувати requirements.txt, бо, хтозна, наступного тижня (а це Різдво) ви отримаєте новий комп’ютер у подарунок, тож вам доведеться знову налаштувати там своє саме середовище.

    • Якщо ви розробляєте бібліотеку, fooякою користуватиметься import foo, вам слід підготувати setup.py. Період. Але ви все одно можете вибрати одночасно надати і файл requirements.txt, який може:

      (а) будь-який із A==1.2.3стилів (як пояснено в №2 вище);

      (б) або просто містять магічний сингл .

      .

      що приблизно дорівнювало б "встановити вимоги на основі setup.py" при цьому без дублювання. Особисто я вважаю, що цей останній підхід розмиває лінію, додає плутанини і насправді НЕ додає вартості, але, тим не менше, це трюк, отриманий із підходу, про який згадував власник упаковки Python Дональд у своєму дописі в блозі .

  3. Різні нижні межі.

    Навіть після того, як ви виконали вищезазначені 3 критерії та правильно вирішили, що ваша бібліотека hybrid-engineвикористовуватиме a setup.pyдля оголошення своєї залежності engine>=1.2.0, а ваша зразок програми reliable-carвикористовуватиме requirements.txtдля оголошення своєї залежності engine>=1.2.3, хоча остання версія engineвже на 1.4.0. Як бачите, ваш вибір для нижнього межового числа все ще дещо відрізняється. І ось чому.

    • hybrid-engineзалежить від того, engine>=1.2.0що, гіпотетично кажучи, необхідна здатність "внутрішнього згоряння" була вперше представлена ​​в Росії engine 1.2.0, і ця можливість є необхідністю hybrid-engine, незалежно від того, чи можуть бути такі (незначні) помилки всередині такої версії та виправлені в наступних версіях 1.2.1 , 1.2.2 та 1.2.3.

    • reliable-carзалежить від engine>=1.2.3того, що це найраніша версія БЕЗ відомих проблем, на даний момент. Звичайно, є нові можливості в пізніших версіях, скажімо, "електродвигун", впроваджений в engine 1.3.0, і "ядерний реактор", введений в engine 1.4.0, але вони не є необхідними для проекту reliable-car.


"Ваша бібліотека не буде (і не повинна) бути" прискіпливою "щодо того, якою точно має бути ВАША залежність." Не могли б ви трохи детальніше розказати це питання? Думаю, ваш код зазвичай тестується лише з конкретними версіями залежностей, і такий підхід може бути трохи небезпечним. Я припускаю, що бібліотека повинна працювати з різними версіями, оскільки ви не хочете встановлювати занадто багато версій залежностей? Щоб заощадити місце на диску?
Таро Кірітані

@TaroKiritani Насправді я перелічив 2 різні сценарії поруч, справу бібліотеки та програму. Можливо, ви раніше не працювали над бібліотекою? Очікується, що вона, як бібліотека, буде споживатися пакунками, що перебувають у нижній течії. Отже, якщо ви вимогливі закріпити ВАШУ залежність A==1.2.3, а потім, якщо випадковий пакет вашої бібліотеки залежить від вас A==1.2.4, зараз не буде способу задовольнити обидва. Рішенням для мінімізації цього конфлікту є те, що ваша бібліотека визначає діапазон, який, на вашу думку, буде працювати. Якщо припустити, що багато попередніх бібліотек вже слідує semver.org , це A>=1,<2буде працювати.
RayLuo

Я не розумів, що лише одну версію пакета можна встановити в одному середовищі. stackoverflow.com/a/6572017/5686692 Дякуємо за роз'яснення.
Таро Кірітані

1
@TaroKiritani, так, інакше як би додаток знати , яка версія fooце import fooдасть вам? Прийнята відповідь у цьому посиланні служить прекрасним прикладом того, чому супровідник пакетів "не повинен і не повинен бути вибагливим". :-) Тепер я можу отримати ваш голос за?
RayLuo

1
Я також міг би прокоментувати цю нову думку, але тоді цей розділ коментарів вже не відповідає темі, і для нових відвідувачів важко стежити. Я б запропонував вам задати нове запитання "Чи використовуватимемо токси або щось інше для того, щоб гарантувати, що моя бібліотека працює над різними комбінаціями залежностей", і тоді люди можуть
підслухати
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.