requirements.txt против setup.py

112

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

Как эти два файла действительно предназначены для использования?

Люси
источник
1
Вы искали в Интернете свое точное название? Эта статья (первое попадание при поиске) - лучшее, что я читал по этой теме.
Крис
2
Эта статья может быть полезна: caremad.io/posts/2013/07/setup-vs-requirement (извините, слишком ленив, чтобы извлекать основные сведения в правильный ответ). Другое дело, что некоторые инструменты (например, тестирование) могут иметь склонность к тому или иному, но пусть это вас не беспокоит, если вы только начали работать над Python.
drdaeman

Ответы:

84

requirements.txt

Это поможет вам настроить среду разработки. Такие программы, как pipможно использовать для установки всех пакетов, перечисленных в файле, одним махом. После этого вы можете приступить к разработке своего скрипта на Python. Это особенно полезно, если вы планируете, чтобы другие участвовали в разработке или использовали виртуальные среды. Вот как вы его используете:

pip install -r requirements.txt

setup.py

Это позволяет вам создавать пакеты, которые вы можете распространять. Этот сценарий предназначен для установки вашего пакета в системе конечного пользователя, а не для подготовки среды разработки, как это pip install -r requirements.txtделается. См. Этот ответ для получения дополнительных сведений о setup.py.

Зависимости вашего проекта перечислены в обоих файлах.

Андреаст
источник
2
В каких случаях у меня будет только один из них? В каком я бы имел оба?
Мартин Тома,
29
Эм ... вы просто пишете для развлечения на своей локальной машине: Ни то, ни другое. Скрипт разработан на нескольких машинах / vitualenv, но не распространяется повторно: requirements.txt. Скрипт разрабатывается только на вашем компьютере, но его следует распространять: setup.py. Скрипт будет распространяться и разрабатываться в нескольких средах: Оба.
AndreasT
Не могли бы вы добавить это к ответу?
Мартин Тома
58

Короткий ответ: только requirements.txtдля перечисления требований к пакету. setup.pyс другой стороны, это больше похоже на сценарий установки. Если вы не планируете устанавливать код Python, обычно вам понадобится только requirements.txt.

Файл setup.pyописывает, помимо зависимостей пакетов, набор файлов и модулей, которые должны быть упакованы (или скомпилированы, в случае собственных модулей (т.е. написанных на C)), и метаданные для добавления в списки пакетов python ( например, имя пакета, версия пакета, описание пакета, автор, ...).

Поскольку в обоих файлах перечислены зависимости, это может привести к небольшому дублированию. Подробности читайте ниже.

requirements.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в данном каталоге (или модуле). Точно так же любой модуль, у которого есть, 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 вне контекста среды разработки вашего проекта.

init_js
источник
7
и вы также можете иметь просто .без него -eвнутри requirements.txt. Этот метод просто делегирует все требования, setup.pyи вам не нужно никого принудительно переводить в редактируемый режим. Пользователи все еще могут делать это, pip install -e .если хотят.
Стасон
1
Интересный трюк с "-e". в файле requirements.txt, но разве это не противоречит той цели, что requirements.txt является точной спецификацией системы? Зачем в таком случае вообще один?
Бен Огорек,
Вы можете указать точные системные требования внутри setup.py. Имея "." в файле requirements.txt используется файл setup.py в текущей папке. Использование -e .также использует setup.py для поиска зависимостей, но связывает текущую папку (на месте, с символической ссылкой) в папке установки pip, а не берет копию - вы -eобычно будете использовать, только если вы разрабатываете пакет. С -e, изменения в ваших файлах пакета python (* .py) вступят в силу немедленно в вашей среде pip, вместо того, чтобы принудительно переустанавливать пакет после каждого изменения.
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 минимальны, файлы требований часто содержат исчерпывающий список закрепленных версий с целью обеспечения повторяемой установки всей среды.

Но это все равно может быть непросто понять, поэтому в следующем разделе приведены два фактических примера, демонстрирующих, как предполагается использовать эти два подхода по-разному.

  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.

RayLuo
источник
«ваша библиотека не будет (и не должна) быть« разборчивой »в отношении того, какой именно версией ВАШИХ зависимостей должна быть». Не могли бы вы немного пояснить этот момент? Я предполагаю, что ваш код обычно тестируется только с определенными версиями зависимостей, и этот подход может быть немного опасным. Я предполагаю, что библиотека должна работать с разными версиями, потому что вы не хотите устанавливать слишком много версий зависимостей? Для экономии места на диске?
Taro
@TaroKiritani На самом деле я перечислил два разных сценария бок о бок, случай библиотеки и случай приложения. Возможно, вы раньше не работали над библиотекой? Ожидается, что как библиотека он будет использоваться последующими пакетами. Так что, если вы придирчивы к тому, чтобы закрепить ВАШУ зависимость A==1.2.3, а затем, если нижестоящий пакет вашей библиотеки зависит A==1.2.4, теперь не будет способа удовлетворить оба. Решение минимизировать этот конфликт состоит в том, что ваша библиотека определяет диапазон, который, как вы знаете, будет работать. Предполагая, что многие апстрим-библиотеки уже подписаны на semver.org , A>=1,<2будет работать.
RayLuo
Я не понимал, что в одной среде может быть установлена ​​только одна версия пакета. stackoverflow.com/a/6572017/5686692 Спасибо за разъяснения.
Taro
1
@TaroKiritani, да, иначе как бы приложение знать , какая версия fooэто import fooдаст вам? Тот хакерский принятый ответ в той ссылке, которую вы предоставили, служит прекрасным примером того, почему сопровождающий пакета «не должен и не должен быть придирчивым». :-) Теперь можно проголосовать за?
RayLuo
1
Я мог бы также прокомментировать эту новую мысль, но тогда этот раздел комментариев уже выходит за рамки темы, и новичкам трудно следовать. Я бы посоветовал вам задать новый вопрос: «Будем ли мы использовать tox или что-то в этом роде, чтобы гарантировать, что моя библиотека работает с различными комбинациями зависимостей», и тогда люди смогут
вмешаться