thacoon's Blog

Bash script for easy Python requirements management

· thacoon

Update

I migrated to Pipenv some time ago and being pretty happy about this.

Outdated article

For every Python project I set up a virtualenv and handle my requirements with pip-tools. It is a command line tool to keep pip-based packages fresh and pinns them. It is my favorite tool to handle Pyhon requirements. Using pip-tools you basically define your requirements in a *.infile and when you run pip-compile it will create a *.txtrequirements files with all dependencies (and all underlying dependencies) pinned. And using pip-sync it will install all packages definied in a requirements file but also uninstall any other package which is not defined.

In most cases I split my requirements files into four categories: base, dev, tests and production. When developing I often have all requirements installed, in my CI only base and tests requirements and on production only base and production requirements.

So over time I approximately came to the following script, that lies as update.sh in the root of my Python projects. On a fresh virtualenv you first need to run pip install pip-tools, change the file permissions chmod 744 update.sh and then the following script can be used.

What it simply does when you run ./update.sh compile it will use pip-tools to create your pinned requirements files.

And then you can install the different combinations with ./update.sh sync-all for all packages, ./update.sh sync-tests for base and test and ./update.sh sync-dev for base, test and dev.

There are also commands which do not require pip-toolsto be installed, these use pipto install all needed dependencies. This is useful for CI environments or production where you install the dependencies only once and dont want unneded extra tools to be installed. You can run ./update sync-ciin the CI to install base and test or ./update sync-productionto install base and production requirements.

 1#!/bin/bash
 2
 3function help {
 4    echo "usage: ./update arguments"
 5    echo "  compile                 Upgrades the pinned version of all packages."
 6    echo "  sync-all                Update your virtual environment of all packages."
 7    echo "  sync-dev                Update your virtual environment for base, dev and test."
 8    echo "  sync-tests              Update your virtual environment for base and test."
 9    echo "  sync-ci                 Update your virtual environment for base and test."
10    echo "  sync-production         Update your virtual environment for base and production."
11    echo "  upgrade                 Upgrades pip, setuptools and pip-tools."
12}
13
14if [ $# -eq  0 ]; then
15    help
16    exit 1
17fi
18
19if [ "$1" == "sync-production" ]; then
20    pip install --no-cache-dir -r requirements/production.txt
21    exit 0
22elif [ "$1" == "sync-ci" ]; then
23    pip install --no-cache-dir -r requirements/tests.txt
24    exit 0
25elif [ "$1" == "upgrade" ]; then
26    pip install --upgrade pip setuptools pip-tools
27    exit 0
28fi
29
30if ! pip list | grep "pip-tools" > /dev/null ; then
31    echo "This action requires pip-tools. Run 'pip install pip-tools' or './update.sh upgrade'."
32    help
33    exit 1
34fi
35
36if [ "$1" == "sync-all" ]; then
37    pip-sync requirements/base.txt requirements/dev.txt requirements/tests.txt requirements/production.txt
38    exit 0
39
40elif [ "$1" == "sync-dev" ]; then
41    pip-sync requirements/base.txt requirements/dev.txt requirements/tests.txt
42    exit 0
43
44elif [ "$1" == "sync-tests" ]; then
45    pip-sync requirements/base.txt requirements/tests.txt
46    exit 0
47
48elif [ "$1" == "compile" ]; then
49    pip-compile --upgrade requirements/base.in -o requirements/base.txt
50    pip-compile --upgrade requirements/base.in requirements/tests.in requirements/dev.in -o requirements/dev.txt
51    pip-compile --upgrade requirements/base.in requirements/tests.in -o requirements/tests.txt
52    pip-compile --upgrade requirements/base.in requirements/production.in -o requirements/production.txt
53
54else
55    help
56    exit 1
57fi

References

#python

Reply to this post by email ↪