install_requires vs requirements.txt

January 30, 2021
 · 2 min read

When I started working at Red Hat my first job was contribution to integration tests of one web application. The tests are written Python and the repository has both and requirements.txt. But why?


Python and many other interpreted languages such as Ruby and JS require a prepared environment to run some code. This environment should have all dependencies installed with correct versions. In Python we use requirements.txt file for describing such environment. It's just a text file with package names and versions. e.g.:


Then using pip we can recreate this environment in any other place. It makes a lot of sense when we deploy a Python application.


But what about dependencies of dependencies? Python code is distributed via packages. A Python package is a directory that follows a certain file structure and has file that is a build script for setuptools. If your package uses other packages you can specify them in install_requires argument:

import setuptools

with open("", "r", encoding="utf-8") as fh:
    long_description =

    name="example-pkg-YOUR-USERNAME-HERE", # Replace with your own username
    author="Example Author",
    description="A small example package",
    install_requires=["pytest>6.0.0", "django"]
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",

Applications vs packages

So we now know packages need only install_requires in in order to specify dependencies. Application and standalone scripts need only requirements.txt for reproducing an environment. Things get more complicated when your package is an application as well. setuptools can generate a python script that can be placed in $PATH. It can call some entry point function in your package. During the deployment we would like to have a reproducible environment and as I told before requirements.txt is what we need to use to recreate such environments.


Let me consider the case that I started the post with. pytest is the best choice for developing tests on any level: unit, functional and integration. The integration tests I worked on are really huge. In order to manage the complexity we created some abstractions to interact with the web application we want to test. These abstractions are organized as a package. In the tests we import that package and in fact we test its code. Let me provide a simplified directory structure:


Interesting thing here is that our tests is the application :) And for deploying our application in CI we need to recreate the environment and that's why we have both and requirements.txt in one repository. Of course nothing prevents you to divide the tests and the package in different repositories but I think it would be inconvenient.


Discuss on Github