Managing FastAPI Projects with Poetry: A Step-by-Step Guide
This guide will walk you through how to use Poetry to manage dependencies and structure your project in FastAPI. It includes detailed explanations of Poetry's core concepts and commands to help prevent issues that can arise during team collaboration and deployment.
1. What is Poetry?
Poetry is a dependency management and packaging tool for Python. It goes beyond simply installing libraries by allowing you to clearly declare the dependencies your project needs and ensuring that all developers on the project have the same library versions.
- Clarity in Dependency Management: Explicitly manage your project's basic information and required libraries through the
pyproject.toml
file. - Reproducible Builds: By locking all dependency versions in the
poetry.lock
file, it fundamentally prevents "it works on my machine" problems. - Integrated Development Environment: It automatically creates and manages isolated virtual environments for each project and handles most project-related tasks—such as dependency installation, script execution, package building, and deployment—with a single
poetry
command.
With Poetry, you don't need to use venv
directly. Poetry handles virtual environment management automatically by internally processing commands like python -m venv .venv
, allowing you to focus solely on dependency management.
2. Poetry and Initial Project Setup
First, you need to have Python and Poetry installed on your system.
Installing Poetry:
The version of Poetry available in Ubuntu's apt
repository is often not the latest official release. The official installer is recommended.
- Latest Version Guaranteed: The official script always installs the latest stable version of Poetry.
- Isolated Installation: The script installs Poetry in the user's home directory (
~/.local/bin
), isolating it from other system packages to prevent conflicts.
You should run the installer as a regular user, not root
. Poetry is installed on a per-user basis, which is safer and allows you to manage environments without needing sudo
privileges.
$ curl -sSL https://install.python-poetry.org | python3 -
After installation, you need to add Poetry's bin
directory to your shell's PATH
. For most shells on Linux and macOS, you can do this by adding the following line to your shell configuration file (e.g., ~/.bashrc
, ~/.zshrc
):
export PATH="$HOME/.local/bin:$PATH"
Remember to restart your shell or run source ~/.bashrc
for the changes to take effect.
$ poetry --version
Poetry (version 1.8.2)
Creating a New FastAPI Project:
Use the poetry new
command to create a new project. It's recommended to use the --src
flag to set up the project with the standard src
layout.
$ poetry new my-fastapi-project
Created package my_fastapi_project in my-fastapi-project
The resulting directory structure is as follows:
$ cd my-fastapi-project
~/my-fastapi-project$ tree
.
├── README.md
├── pyproject.toml
├── src
│ └── my_fastapi_project
│ └── __init__.py
└── tests
└── __init__.py
4 directories, 4 files
3. Understanding Dependency Management: add
, lock
, and install
Poetry's dependency management revolves around two files, pyproject.toml
and poetry.lock
, and three core commands that handle them.
pyproject.toml vs. poetry.lock
pyproject.toml
: This is the blueprint for your project. You, the developer, define the necessary libraries and their allowed version ranges, likefastapi = "^0.116.1"
.poetry.lock
: This is the precise specification for your project. Poetry automatically finds and records the specific versions that satisfy the ranges inpyproject.toml
(e.g.,version = "0.111.1"
). You should never manually edit this file. It must be committed to Git and shared with your team.
Core Commands
1. poetry add [package-name]
(Adding a dependency)
- This is the most commonly used command.
- When you add a new library, it performs the following three tasks automatically and at once:
- Adds the package as a dependency to
pyproject.toml
. - Updates the
poetry.lock
file to lock the versions of the new and existing packages. - Installs the package into the virtual environment.
- Adds the package as a dependency to
2. poetry lock
(Locking dependency versions)
- Reads the
pyproject.toml
file to create or update thepoetry.lock
file. - It does not install any packages; it only updates the version information in the
poetry.lock
file. - Use this when you have manually edited the
pyproject.toml
file and want to synchronize it withpoetry.lock
.
3. poetry install
(Installing dependencies)
- Installs all packages with the exact versions specified in the
poetry.lock
file. - When you first clone a project from Git or pull updates to
poetry.lock
from a teammate, use this command to ensure everyone has an identical development environment. - If a
poetry.lock
file does not exist, it will first run thepoetry lock
command to create one and then proceed with the installation.
Practical Example
Installing FastAPI and Uvicorn:
Use the poetry add
command to add FastAPI and the ASGI server Uvicorn as project dependencies.
$ poetry add fastapi uvicorn
Using version ^0.116.1 for fastapi
Using version ^0.35.0 for uvicorn
Updating dependencies
Resolving dependencies... (0.8s)
No dependencies to install or update
Writing lock file
Now, both pyproject.toml
and poetry.lock
are updated, and the two packages are installed in your virtual environment.
Adding Development Dependencies:
Libraries used for testing or code formatting should be managed as development dependencies using the --group dev
(or -D
) option.
$ poetry add pytest httpx --group dev
Using version ^8.4.1 for pytest
Using version ^0.28.1 for httpx
Updating dependencies
Resolving dependencies... (1.0s)
Package operations: 8 installs, 0 updates, 0 removals
- Installing certifi (2025.7.14)
- Installing httpcore (1.0.9)
- Installing iniconfig (2.1.0)
- Installing packaging (25.0)
- Installing pluggy (1.6.0)
- Installing pygments (2.19.2)
- Installing httpx (0.28.1)
- Installing pytest (8.4.1)
Writing lock file
pytest
and httpx
will be added to the [tool.poetry.group.dev.dependencies]
section in pyproject.toml
. These dependencies will not be installed in a production environment.
4. Writing the Application
Create a main.py
file inside the my_fastapi_project
directory and write a simple FastAPI application.
src/my_fastapi_project/main.py
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
5. Running the Development Server
The poetry run
command executes a command within the virtual environment managed by Poetry. You don't need to manually activate the virtual environment with commands like source .venv/bin/activate
.
$ poetry run uvicorn my_fastapi_project.main:app --reload --port 8084
INFO: Will watch for changes in these directories: ['/home/jason/my-fastapi-project/src']
INFO: Uvicorn running on http://127.0.0.1:8084 (Press CTRL+C to quit)
INFO: Started reloader process [1546799] using StatReload
INFO: Started server process [1546806]
INFO: Waiting for application startup.
INFO: Application startup complete.
my_fastapi_project.main:app
: Refers to theapp
instance inside themain.py
file within the my_fastapi_project` package.--reload
: A useful development option that automatically restarts the server whenever you change the code.
Now, open your browser to http://127.0.0.1:8084
to see the "Hello": "World" message, and visit http://127.0.0.1:8084/docs
to see the auto-generated API documentation.
6. Managing Commands with Scripts
Instead of typing long commands every time, you can register them as scripts in your pyproject.toml
file for convenience.
Create a cli.py
file inside the my_fastapi_project
directory and write a script.
src/my_fastapi_project/cli.py:
import uvicorn
import pytest
def dev():
uvicorn.run("my_fastapi_project.main:app", reload=True, port=8084)
def runtests():
raise SystemExit(pytest.main())
Add the following section to your pyproject.toml
file:
[tool.poetry.scripts]
dev = "my_fastapi_project.cli:dev"
test = "my_fastapi_project.cli:runtests"
Now you can easily run the development server and tests with these commands:
$ poetry run dev
INFO: Will watch for changes in these directories: ['/home/jason/my-fastapi-project']
INFO: Uvicorn running on http://127.0.0.1:8084 (Press CTRL+C to quit)
INFO: Started reloader process [1547940] using StatReload
INFO: Started server process [1547948]
INFO: Waiting for application startup.
INFO: Application startup complete.
7. Writing and Running Tests
Write your test code in the tests
directory. FastAPI provides a TestClient
that makes it easy to test your application.
tests/test_main.py:
from fastapi.testclient import TestClient
from my_fastapi_project.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"Hello": "World"}
def test_read_item():
response = client.get("/items/5?q=somequery")
assert response.status_code == 200
assert response.json() == {"item_id": 5, "q": "somequery"}
You can run the tests easily with the script you registered earlier:
$ poetry run test
$~/my-fastapi-project$ poetry run pytest
==================== test session starts ====================
platform linux -- Python 3.12.3, pytest-8.4.1, pluggy-1.6.0
rootdir: /home/gcp/my-fastapi-project
configfile: pyproject.toml
plugins: anyio-4.9.0
collected 2 items
tests/test_main.py ..
[100%]
==================== 2 passed in 0.45s ====================
We hope this guide has helped you learn how to effectively build and manage your development environment in a FastAPI project using Poetry. 🎉
Comments
Post a Comment