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

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

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


person lucy    schedule 27.04.2017    source источник
comment
Вы искали в Интернете свое точное название? Эта статья (первое попадание при поиске) - лучшая Я читал по теме.   -  person Chris    schedule 27.04.2017
comment
Эта статья может быть полезна: caremad.io/posts/2013/07/setup -vs-require (извините, слишком ленив, чтобы извлекать основную информацию в правильный ответ). Другое дело, что некоторые инструменты (например, тестирование) могут иметь склонность к тому или иному, но пусть это вас не беспокоит, если вы только начали работать над Python.   -  person drdaeman    schedule 27.04.2017
comment
В чем преимущество этого (setup.py или requirements.txt) по сравнению с простым .sh сценарием, когда я conda / pip установил каждый пакет?   -  person Charlie Parker    schedule 23.04.2021


Ответы (3)


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.


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

person AndreasT    schedule 27.04.2017
comment
В каких случаях у меня будет только один из них? В котором я бы взял и то, и другое? - person Martin Thoma; 25.02.2018
comment
Эм ... вы просто пишете для развлечения на своей локальной машине: Ни то, ни другое. Скрипт разработан на нескольких машинах / vitualenv, но не распространяется: requirements.txt. Скрипт разрабатывается только на вашем компьютере, но его следует распространять: setup.py. Скрипт будет распространяться и разрабатываться в нескольких средах: Оба. - person AndreasT; 26.02.2018
comment
Не могли бы вы добавить это к ответу? - person Martin Thoma; 26.02.2018
comment
Вы когда-нибудь действительно имели бы setup.py без requirements.txt? Спрашиваю друга, который совершенно не понимает этого. - person eric; 21.10.2020
comment
В чем преимущество этого (setup.py или requirements.txt) по сравнению с простым .sh сценарием, когда я conda / pip установил каждый пакет? - person Charlie Parker; 23.04.2021
comment
@CharlieParker Ну, setup.py - это интеграция с кроссплатформенным механизмом установки и упаковки Python, а файл requirements.txt в основном является условным. Как это часто бывает с foss: вы, конечно, можете свернуть свою собственную, но, вероятно, не должны. - person AndreasT; 24.04.2021
comment
@AndreasT что означает перераспределение? - person Charlie Parker; 14.07.2021

Короткий ответ: 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. Примеры недостатков средств установки - невозможность установить несколько версий одного и того же пакета и отсутствие команды удаления.

Когда пользователь 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 вне контекста среды разработки вашего проекта.

person init_js    schedule 06.04.2018
comment
и вы также можете иметь только . без -e внутри requirements.txt. Этот метод просто делегирует все требования setup.py, и вам не нужно никого принудительно переводить в редактируемый режим. Пользователи по-прежнему могут делать pip install -e ., если хотят. - person stason; 17.10.2018
comment
Интересный трюк с -e. в файле requirements.txt, но разве это не противоречит той цели, что requirements.txt является точной спецификацией системы? Зачем в таком случае вообще один? - person Ben Ogorek; 11.02.2020
comment
Вы можете указать точные системные требования внутри setup.py. Имея. в файле requirements.txt используется файл setup.py в текущей папке. Использование -e . также использует setup.py для поиска зависимостей, но связывает текущую папку (на месте, с символической ссылкой) в папке установки pip, вместо того, чтобы делать копию - вы бы использовали -e, как правило, только если вы разрабатываете упаковка. С -e изменения в файлах пакета python (* .py) вступят в силу немедленно в среде pip, вместо того, чтобы принудительно переустанавливать пакет после каждого изменения. - person init_js; 22.02.2020
comment
@init_js - это текущая папка относительно файла требований или CWD, из которого вызывается pip? Т.е. если вы сделаете cd foo && pip install -r ./bar/requirements.txt, будет ли он искать setup.py в foo/bar или foo? Если второе, есть ли способ достичь первого? - person Dan M.; 14.07.2020
comment
pip -r REQ не заботится о каталоге, в котором находится REQ. Вы можете кормить его из фифо, даже если хотите: pip install -r <(echo "mylib1"; echo "mylib2";). Где <(CMD) - это подстановка команды bash, а не перенаправление стандартного ввода. - person init_js; 15.07.2020
comment
@stason. вы также можете просто ., без -э Я согласен. Но когда вы говорите, что пользователи все еще могут выполнять pip install -e, я думаю, вы имеете в виду разработчиков. Большинство пользователей будут устанавливать pip-пакет из репозиториев пакетов или через easyinstall pypi. - person init_js; 22.07.2020
comment
В чем преимущество этого (setup.py или requirements.txt) по сравнению с простым .sh сценарием, когда я conda / pip установил каждый пакет? - person Charlie Parker; 23.04.2021
comment
Библиотекам @BenOgorek нужен только setup.py, а не requirements.txt. Вы не хотите писать библиотеку в искусственно ограниченной среде разработки (с более жесткими ограничениями версии, исходящими из файла requirements.txt), потому что у ваших пользователей не будет такой аккуратной ситуации. Они увидят жизнь только через призму setup.py. Но для некоторых систем CI требуется файл requirements.txt. Это ситуация, когда уловка с точкой помогает. - person FMc; 30.04.2021

Для полноты картины вот как я это вижу в 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
    
  1. На самом деле, что мне использовать?

    • Если вы разрабатываете приложение bar, которое будет использоваться python bar.py, даже если это просто сценарий для развлечения, вам все равно рекомендуется использовать файл requirements.txt, потому что, кто знает, на следующей неделе (а это Рождество) вы получите новый компьютер в подарок, так что вам нужно будет снова настроить там вашу точную среду.

    • Если вы разрабатываете библиотеку foo, которая будет использоваться import foo, вам необходимо подготовить setup.py. Период. Но вы все равно можете одновременно предоставить файл requirements.txt, который может:

      (а) быть в стиле A==1.2.3 (как объяснено в пункте 2 выше);

      (б) или просто содержать волшебный сингл .

         .
      

      Последний по существу использует обычную requirements.txt привычку документировать шаг установки pip install ., что означает установку требований на основе setup.py без дублирования. Лично я считаю, что этот последний подход размывает границы, добавляет путаницы, но, тем не менее, это удобный способ явно отказаться от закрепления зависимостей при работе в среде CI. Уловка была получена из подхода, упомянутого разработчиком упаковки Python Дональдом в своем сообщении в блоге.

  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
    

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

person RayLuo    schedule 11.12.2018
comment
ваша библиотека не будет (и не должна) быть «разборчивой» в отношении того, какая именно версия ВАШИХ зависимостей должна быть. Не могли бы вы немного уточнить этот момент? Я предполагаю, что ваш код обычно тестируется только с определенными версиями зависимостей, и этот подход может быть немного опасным. Я предполагаю, что библиотека должна работать с разными версиями, потому что вы не хотите устанавливать слишком много версий зависимостей? Чтобы сэкономить место на диске? - person Taro Kiritani; 23.07.2019
comment
@TaroKiritani На самом деле я перечислил два разных сценария бок о бок, случай библиотеки и случай приложения. Возможно, вы раньше не работали над библиотекой? Ожидается, что как библиотека он будет использоваться последующими пакетами. Итак, если вы придирчивы к закреплению ВАШЕЙ зависимости A==1.2.3, а затем, если нижестоящий пакет вашей библиотеки будет зависеть от A==1.2.4, теперь не будет способа удовлетворить оба. Решение минимизировать этот конфликт состоит в том, что ваша библиотека определяет диапазон, который, как вы знаете, будет работать. Предполагая, что многие исходные библиотеки уже следуют за semver.org, A>=1,<2 будет работать. - person RayLuo; 23.07.2019
comment
Я не понимал, что только одна версия пакета может быть установлена ​​в одной среде. stackoverflow.com/a/6572017/5686692 Спасибо за разъяснения. - person Taro Kiritani; 23.07.2019
comment
@TaroKiritani, ага, иначе как ваше приложение узнало бы, какая версия foo дает вам import foo? Эти взломанные принятые ответы в указанной вами ссылке служит прекрасным примером того, почему разработчик пакетов не должен и не должен быть разборчивым. :-) Теперь можно проголосовать за? - person RayLuo; 23.07.2019
comment
Я полагаю, что тогда нам нужно использовать tox или что-то в этом роде, чтобы гарантировать, что моя библиотека работает с различными комбинациями зависимостей. Однако проверка всех комбинаций версий зависимостей может оказаться довольно затратной. Я бы хотел, чтобы у нас была возможность импортировать определенную версию, например import foo==1.0 или что-то в этом роде. - person Taro Kiritani; 25.07.2019
comment
Я мог бы также прокомментировать эту новую мысль, но тогда этот раздел комментариев уже выходит за рамки темы, и новичкам трудно следовать. Я предлагаю вам задать новый вопрос. Будем ли мы использовать tox или что-то еще, чтобы гарантировать, что моя библиотека работает с различными комбинациями зависимостей, и тогда люди смогут вмешаться. - person RayLuo; 26.07.2019
comment
В чем преимущество этого (setup.py или requirements.txt) по сравнению с простым .sh сценарием, когда я conda / pip установил каждый пакет? - person Charlie Parker; 23.04.2021
comment
@CharlieParker, если вы разрабатываете библиотеку foo, которая будет использоваться при импорте foo, вы должны подготовить setup.py. Период. Потому что ваша нижележащая библиотека или приложение не сможет запустить ваш .sh скрипт. Но, судя по вашему вопросу, я полагаю, что вы не разработчик библиотеки. Тогда да, вы можете пойти любым путем, вам просто нужно задокументировать шаги установки для вашего конечного пользователя. Тем не менее, я все равно буду утверждать, что одна зависимость на строку requirements.txt более универсальна и питонична, чем .sh. Что делать, если ваш конечный пользователь работает с Windows, которая не может работать .sh? - person RayLuo; 24.04.2021
comment
Очень полезный ответ - и ссылка на сообщение в блоге Дональда Стаффта. Решил для меня проблему, так что спасибо. Я действительно думаю, что вы недооцениваете ценность использования разработчиками библиотек (меня) трюка с волшебными точками в файле requirements.txt. Мне как разработчику библиотеки не нужен / не нужен файл requirements.txt, потому что моим пользователям будет доступен только файл setup.py. Однако некоторые системы CI требуют этого. Таким образом, волшебная точка упростит мою жизнь, поскольку мне не придется дублировать список зависимостей. - person FMc; 30.04.2021
comment
@FMc, спасибо за ваш голос и отзыв! Я тоже сопровождаю библиотеку. Я думаю, что то, что вы сказали, было правильным, поэтому я соответствующим образом обновил свой ответ. Спасибо! - person RayLuo; 30.04.2021