Python Development Workflow with uv
#
uv is the newest tool taking the Python world by storm — it helps simplify the management of multiple Python versions, virtual environments, and package installation.
If you’re new to Python, we recommend following our “normal” Python Development Workflow first.
Step 1: Install uv
#
Open a terminal and run the following command to download and install:
% curl -LsSf https://astral.sh/uv/install.sh | sh
Alternatively, download and unzip the binary from: https://github.com/astral-sh/uv/releases.
Additional installation methods are documented here: https://docs.astral.sh/uv/.
Open a terminal and install using winget, which is included with Windows 10 and 11:
PS> winget install astral-sh.uv
After installation, close your Terminal and open a new one for the changes to take effect.
Alternatively, download and unzip the binary from: https://github.com/astral-sh/uv/releases.
Open a terminal and run the following command to download and install:
$ curl -LsSf https://astral.sh/uv/install.sh | sh
Alternatively, download and unzip the binary from: https://github.com/astral-sh/uv/releases.
Additional installation methods are documented here: https://docs.astral.sh/uv/.
Step 2: Create a project directory#
Creating a dedicated directory (commonly called a folder) is a good starting point. This is often called your project folder, project directory, project dir, or project root.
We recommend storing all of your code in central directory, called “Source”, within your home directory. In this guide, we’ll refer to ~/Source/
. We’ll also refer to your project as myproject
.
If you’re working on a project with a git repo, start by cloning that repo:
% cd ~/Source
% git clone <myproject-url>
PS> cd ~/Source
PS> git clone <myproject-url>
$ cd ~/Source
$ git clone <myproject-url>
If you’re starting a new project, create a new directory and initialize an empty git repo.
% cd ~/Source
% mkdir myproject
% cd myproject
% git init .
PS> cd ~/Source
PS> mkdir myproject
PS> cd myproject
PS> git init .
$ cd ~/Source
$ mkdir myproject
$ cd myproject
$ git init .
Step 3: Create a virtual environment#
Python projects require installing additional 3rd-party packages, such as Django. However, this creates a problem — what if two different projects need two different versions of a package? You’d then have to uninstall and reinstall every time you switched between the projects, which could cause a lot of problems.
Python includes a solution: “virtual environments”, referred to as venv
. A venv
is simply a folder which contains a separate copy of Python and all the installed packages. This way, each project won’t interfere with any others on your machine.
uv
completely handles virtual environments for you behind the scenes. Simply specify the version of Python you want, and uv
will download and install it.
% cd ~/Source/myproject
% uv venv --python 3.13
PS> cd ~/Source/myproject
PS> uv venv --python 3.13
$ cd ~/Source/myproject
$ uv venv --python 3.13
Step 4: Running Python commands with uv
#
Since uv
manages the Python environment for you, you’ll need to always invoke any Python commands by using uv run <command>
. For example, to run the Python interpreter:
% cd ~/Source/myproject
% uv run python
>>> exit()
PS> cd ~/Source/myproject
PS> uv run python
>>> exit()
$ cd ~/Source/myproject
$ uv run python
>>> exit()
Step 5: Manage pip packages#
To install packages, it is necessary to keep a list of all the packages required by this project. The file containing this list is named requirements.txt
. If you’re working on a new project, go ahead and create or edit the requirements.txt
file in your project directory. In this example, let’s install Django version 5.1.
# Inside the requirements.txt file.
django==5.1.*
Here’s an explanation of what the special syntax means:
django
is the name of the package.==
means to install a version equal to…5.1.*
means any version matching 5.1. Django frequently releases security patches, such as 5.1.1, 5.1.2, 5.1.3, etc. These patches are guaranteed to be backwards compatible, so you usually want the latest to automatically be installed, hence the*
.
Follow this same process for every package you need.
Now that you have a requirements.txt
, install it using uv
as so:
% uv pip install -r requirements.txt
PS> uv pip install -r requirements.txt
$ uv pip install -r requirements.txt
Step 6: Improve quality with developer tools#
“Linters”, which are tools that check your code for errors, can drastically help improve the quality of your code, and are essential for producing professional software.
Since these tools are only used by humans writing code, and are not used in the production web server, we will separate them into a requirements-dev.txt
file, as so:
# Inside requirements-dev.txt file.
# First, install project requirements.
-r requirements.txt
# Now, install developer tools.
ruff
In this file, we are first installing everything from the main requirements.txt
, then installing one additional tool: ruff
. Ruff can format your Python code and also check for errors.
Now, let’s install, then run ruff:
% uv pip install -r requirements-dev.txt
% uv run ruff check --fix
% uv run ruff format
PS> uv pip install -r requirements-dev.txt
PS> uv run ruff check --fix
PS> uv run ruff format
$ uv pip install -r requirements-dev.txt
$ uv run ruff check --fix
$ uv run ruff format
You might see that ruff reformatted your code, or is telling you to fix some errors. Run this every time you make changes to your code.
Step 7: Django & Wagtail specific instructions#
At this point, your Python environment is all set up and working. However, Django & Wagtail projects usually need a MySQL or PostgreSQL database. To get that working in your development environment, need to follow one of these guides:
Finally, every time you make a change to a model in your Django or Wagtail project, you should be sure to create and run migrations. Migrations synchronize those changes in your Django models with your database.
% uv manage.py makemigrations
% uv python manage.py migrate
PS> uv python manage.py makemigrations
PS> uv python manage.py migrate
$ uv python manage.py makemigrations
$ uv python manage.py migrate
Step 8: Git commit#
If you’re using git
, you’ll want to follow our Git Workflow. However, this is your reminder to commit and push any changes before logging off for the day!
Note
Never commit your .venv
folder to git. This is because it is specific to your machine, and won’t work on other people’s machines. It is also very large and will slow down your git repository.
If running git status
shows files from the .venv
folder, then you’ll want to create or edit a file named .gitignore
in your project directory. Copy the contents of this file into your .gitignore
: https://www.toptal.com/developers/gitignore/api/django.