Create a Modern Python Project
This guide will walk you through everything you need to know to set up a Python project repository with the most up-to-date tools.
You can set up your project in many different ways, but this is an opinionated guide based on my own experience of what works well.
This guide is based on using a Mac, but it should also work for Linux or using Windows Subsystem for Linux although some modifications may be necessary for your particular system.
Create a Git Repository
First create a new empty repo on GitHub or a similar service. You'll want to grab the SSH URL of the new git repo and then clone it and cd into it:
cd ~/projects
git clone git@github.com:<username>/<project-name>.git
cd <project-name>Install uv for Python and package management
You probably have a version of Python pre-installed onto your computer already, as it is included with many operating systems by default.
- run
python --versionto find the version of Python you have installed. - run
which pythonto find the full path of your default Python installation.
I don't recommend using the default Python installation to build your own projects, because when you collaborate on it you'll come across issues from different people having different versions of Python on their computers.
The Python core team is constantly creating awesome new features that get released in new versions, so I encourage you to use the latest version of Python available to take advantage of all of them.
I'll show you how you can use uv to manage everything Python-related: installing Python versions, managing packages, creating virtual environments, and running scripts. uv is an extremely fast Python package and project manager written in Rust that handles all of these tasks seamlessly that the Python community is quickly coalescing around.
Install uv by running the official installer script:
curl -LsSf https://astral.sh/uv/install.sh | shYou can also use Homebrew on macOS if you prefer:
brew install uvuv will automatically download and install Python versions as needed, so you don't need to worry about managing Python installations separately. When you specify a Python version for your project, uv will handle downloading the precompiled binaries if they're not already available.
Initialize your project with uv
Now that you have uv installed and your Git repository set up, you can initialize your Python project. Navigate to your cloned repository directory and run:
uv init --python 3.13The --python 3.13 flag specifies which Python version to use for this project. If you don't have Python 3.13 installed, uv will automatically download and install it for you.
This command creates several files automatically:
pyproject.toml- Project metadata and dependencies (similar topackage.json)README.md- Basic project documentationsrc/your_project/- Python package structure.gitignore- Ignores Python-generated files and the.venvdirectory.python-version- Specifies the Python version for the project
The generated .gitignore includes all the standard Python files you want to ignore (like __pycache__/, *.pyc, .venv/, etc.), so you don't need to create one manually.
uv automatically creates and manages a virtual environment in a .venv directory in your project. You don't need to activate or deactivate it manually - uv handles this transparently when you run commands.
Managing dependencies
To add dependencies to your project, use uv add:
uv add requests
uv add pytest --dev # for development dependenciesThis automatically updates your pyproject.toml file and creates a uv.lock file that locks your dependencies to specific versions for reproducible builds.
Locking dependencies with uv lock
Whenever you add or update dependencies, uv automatically creates or updates a uv.lock file. You can also manually generate or update this lockfile:
uv lockThe lockfile is crucial because it:
- Ensures reproducibility: Everyone who works on the project gets the exact same dependency versions
- Includes transitive dependencies: It locks not just your direct dependencies, but all the dependencies of your dependencies
- Prevents "works on my machine" issues: The same versions are installed across development, testing, and production environments
- Enables faster installs:
uvcan install directly from the lockfile without having to resolve dependencies
Important: Always commit your uv.lock file to version control. This ensures that everyone on your team (and your deployment systems) use identical dependency versions.
To install dependencies from an existing project (like when someone else clones your repo), use:
uv syncThis reads the uv.lock file and installs the exact versions specified, ensuring everyone has the same environment.
Running your code
Use uv run to execute Python scripts or modules:
uv run main.py
uv run -m pytest # run pytest moduleuv automatically uses the correct Python version and virtual environment for your project.
You can also use uvx to run tools in isolated environments without installing them globally:
uvx ruff check # run ruff linter
uvx black . # run black formatterBonus: Standalone scripts with inline dependencies
One of uv's coolest features is the ability to create standalone Python scripts with their dependencies declared right in the file. This is perfect when you want to write a quick script without setting up a full project.
Create a script with inline dependencies using:
uv init --script my-script.pyOr manually create a script like this:
#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.9"
# dependencies = [
# "requests",
# "rich"
# ]
# ///
import requests
from rich import print
response = requests.get("https://api.github.com/user", auth=("user", "pass"))
print(response.json())Run it with uv run my-script.py and uv will automatically create a virtual environment, install the dependencies, and execute the script. This is incredibly useful for one-off scripts, data analysis, or experimenting with new libraries.
You can also run scripts with temporary dependencies:
uv run --with pandas my-data-script.pyCongratulations! You're now set up with a modern Python project using the fastest tooling available.
Run the following commands to save the configuration and push to GitHub:
git add -A .
git commit -m "set up python project skeleton"
git pushMake sure to commit your uv.lock file along with your pyproject.toml - this ensures everyone gets the same dependency versions when they run uv sync.