I have a requirements.txt
file that I'm using with Travis-CI. It seems silly to duplicate the requirements in both requirements.txt
and setup.py
, so I was hoping to pass a file handle to the install_requires
kwarg in setuptools.setup
.
Is this possible? If so, how should I go about doing it?
Here is my requirements.txt
file:
guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4
You can flip it around and list the dependencies in
setup.py
and have a single character — a dot.
— inrequirements.txt
instead.Alternatively, even if not advised, it is still possible to parse the
requirements.txt
file (if it doesn't refer any external requirements by URL) with the following hack (tested withpip 9.0.1
):This doesn't filter environment markers though.
In old versions of pip, more specifically older than 6.0, there is a public API that can be used to achieve this. A requirement file can contain comments (
#
) and can include some other files (--requirement
or-r
). Thus, if you really want to parse arequirements.txt
you can use the pip parser:The following interface became deprecated in pip 10:
So I switched it just to the simple text parsing:
While not an exact answer to the question, I recommend Donald Stufft's blog post at https://caremad.io/2013/07/setup-vs-requirement/ for a good take on this problem. I've been using it to great success.
In short,
requirements.txt
is not asetup.py
alternative, but a deployment complement. Keep an appropriate abstraction of package dependencies insetup.py
. Setrequirements.txt
or more of 'em to fetch specific versions of package dependencies for development, testing, or production.E.g. with packages included in the repo under
deps/
:pip executes package's
setup.py
and installs the specific versions of dependencies declared ininstall_requires
. There's no duplicity and the purpose of both artifacts is preserved.Another possible solution...
and then to use...
Install the current package in Travis. This avoids the use of a
requirements.txt
file. For example:On the face of it, it does seem that
requirements.txt
andsetup.py
are silly duplicates, but it's important to understand that while the form is similar, the intended function is very different.The goal of a package author, when specifying dependencies, is to say "wherever you install this package, these are the other packages you need, in order for this package to work."
In contrast, the deployment author (which may be the same person at a different time) has a different job, in that they say "here's the list of packages that we've gathered together and tested and that I now need to install".
The package author writes for a wide variety of scenarios, because they're putting their work out there to be used in ways they may not know about, and have no way of knowing what packages will be installed alongside their package. In order to be a good neighbor and avoid dependency version conflicts with other packages, they need to specify as wide a range of dependency versions as can possibly work. This is what
install_requires
insetup.py
does.The deployment author writes for a very different, very specific goal: a single instance of an installed application or service, installed on a particular computer. In order to precisely control a deployment, and be sure that the right packages are tested and deployed, the deployment author must specify the exact version and source-location of every package to be installed, including dependencies and dependency's dependencies. With this spec, a deployment can be repeatably applied to several machines, or tested on a test machine, and the deployment author can be confident that the same packages are deployed every time. This is what a
requirements.txt
does.So you can see that, while they both look like a big list of packages and versions, these two things have very different jobs. And it's definitely easy to mix this up and get it wrong! But the right way to think about this is that
requirements.txt
is an "answer" to the "question" posed by the requirements in all the varioussetup.py
package files. Rather than write it by hand, it's often generated by telling pip to look at all thesetup.py
files in a set of desired packages, find a set of packages that it thinks fits all the requirements, and then, after they're installed, "freeze" that list of packages into a text file (this is where thepip freeze
name comes from).So the takeaway:
setup.py
should declare the loosest possible dependency versions that are still workable. Its job is to say what a particular package can work with.requirements.txt
is a deployment manifest that defines an entire installation job, and shouldn't be thought of as tied to any one package. Its job is to declare an exhaustive list of all the necessary packages to make a deployment work.References: