I started working with Python. I've added requirements.txt
and setup.py
to my project. But, I am still confused about the purpose of both files. I have read that setup.py
is designed for redistributable things and that requirements.txt
is designed for non-redistributable things. But I am not certain this is accurate.
How are those two files truly intended to be used?
The short answer is that
requirements.txt
is for listing package requirements only.setup.py
on the other hand is more like an installation script.setup.py
describes, in addition to the package dependencies, the set of files and modules that should be packaged (or compiled, in the case of native modules (i.e., written in C)), and metadata to add to the python package listings (e.g. package name, package version, package description, author, ...).Because both files list dependencies, this can lead to a bit of duplication. Read below for details.
requirements.txt
This file lists python package requirements. It is a plain text file (optionally with comments) that lists the package dependencies of your python project (one per line). It does not describe the way in which your python package is installed. You would generally consume the requirements file with
pip install -r requirements.txt
.The filename of the text file is arbitrary, but is often
requirements.txt
by convention. When exploring source code repositories of other python packages, you might stumble on other names, such asdev-dependencies.txt
ordependencies-dev.txt
. Those serve the same purpose asdependencies.txt
but generally list additional dependencies of interest to developers of the particular package, namely for testing the source code (e.g. pytest, pylint, etc.) before release. Users of the package generally wouldn't need the entire set of developer dependencies to run the package.If multiple
requirements-X.txt
variants are present, then usually one will list runtime dependencies, and the other build-time, or test dependencies. Some projects also cascade their requirements file, i.e. when one requirements file includes another file (example). Doing so can reduce repetition.setup.py
This is a python script which uses the
setuptools
module to define a python package (name, files included, package metadata, and installation). It will, likerequirements.txt
, also list runtime dependencies of the package. Setuptools is the de-facto way to build and install python packages, but it has its shortcomings, which over time have sprouted the development of new "meta-package managers", like pip. Example shortcomings of setuptools are its inability to install multiple versions of the same package, and lack of an uninstall command.When a python user does
pip install ./pkgdir_my_module
(orpip install my-module
), pip will runsetup.py
in the given directory (or module). Similarly, any module which has asetup.py
can bepip
-installed, e.g. by runningpip install .
from the same folder.Do I really need both?
Short answer is no, but it's nice to have both. They achieve different purposes, but they can both be used to list your dependencies.
There is one trick you may consider to avoid duplicating your list of dependencies between
requirements.txt
andsetup.py
. If you have written a fully workingsetup.py
for your package already, and your dependencies are mostly external, you could consider having a simplerequirements.txt
with only the following:The
-e
is a specialpip install
option which installs the given package in editable mode. Whenpip -r requirements.txt
is run on this file, pip will install your dependencies via the list in./setup.py
. The editable option will place a symlink in your install directory (instead of an egg or archived copy). It allows developers to edit code in place from the repository without reinstalling.You can also take advantage of what's called "setuptools extras" when you have both files in your package repository. You can define optional packages in setup.py under a custom category, and install those packages from just that category with pip:
and then, in the requirements file:
This would keep all your dependency lists inside setup.py.
Note: You would normally execute pip and setup.py from a sandbox, such as those created with the program
virtualenv
. This will avoid installing python packages outside the context of your project's development environment.For the sake of completeness, here is how I see it in 3 different angles.
This is the precise description quoted from the official documentation (emphasis mine):
But it might still not easy to be understood, so in next section, there come 2 factual examples to demonstrate how the 2 approaches are supposed to be used, differently.
Their actual usages are therefore (supposed to be) different
If your project
foo
is going to be released as a standalone library (meaning, others would probably doimport foo
), then you (and your downstream users) would want to have a flexible declaration of dependency, so that your library would not (and it must not) be "picky" about what exact version of YOUR dependencies should be. So, typically, your setup.py would contain lines like this:If you just want to somehow "document" or "pin" your EXACT current environment for your application
bar
, meaning, you or your users would like to use your applicationbar
as-is, i.e. runningpython bar.py
, you may want to freeze your environment so that it would always behave the same. In such case, your requirements file would look like this:In reality, which one do I use?
If you are developing an application
bar
which will be used bypython bar.y
, even if that is "just script for fun", you are still recommended to use requirements.txt because, who knows, next week (which happens to be Christmas) you would receive a new computer as a gift, so you would need to setup your exact environment there again.If you are developing a library
foo
which will be used byimport foo
, you have to prepare a setup.py. Period. But you may still choose to provide a requirements.txt, which can: (a) either be in theA==1.2.3
style (as explained in #2 above); (b) or just contain a magical.
which would roughly equal to "install the requirements based on setup.py" while without duplication. Personally I consider this last approach kind of blurs the line, adds to the confusion and does NOT really add value, but it is nonetheless a trick derived from an approach mentioned by Python packaging maintainer Donald in his blog post.requirements.txt
This helps you to set up your development environment. Programs like
pip
can be used to install all packages listed in the file in one fell swoop. After that you can start developing your python script. Especially useful if you plan to have others contribute to the development or use virtual environments. This is how you use it:setup.py
This allows you to create packages that you can redistribute. This script is meant to install your package on the end user's system, not to prepare the development environment as
pip install -r < requirements.txt
does. See this answer for more details on setup.py.The dependencies of your project are listed in both files.