The go-to resource for upgrading Python, Django, Flask, and your dependencies.

Migrate from requirements.txt to pyproject.toml: 5-Step Process for Flask Applications


Python projects traditionally managed dependencies with pip install -r requirements.txt. While straightforward, requirements.txt files lack lockfiles, leading to inconsistent installs across environments. Modern pyproject.toml (PEP 518/621) with tools like Poetry provides declarative dependencies, lockfiles (poetry.lock), and reproducible builds—particularly suitable for Flask web apps in production.

We’ll follow this 5-step process to migrate a Flask project, as tested with Python 3.12 and Flask 3.0.

Why Migrate for Flask Apps?

  • Reproducibility: poetry.lock pins exact versions, preventing “works on my machine” issues.
  • Speed: Typically faster poetry install than pip install -r requirements.txt.
  • Standards: Aligns with Python’s future; supports scripts, plugins, build reqs.
  • Flask Benefits: Handles dev/prod deps (e.g., flask[async]), Gunicorn, etc.

Choosing Your Dependency Tool

Poetry excels with lockfiles and simple syntax, but consider these alternatives:

  • pip-tools: pip-compile requirements.in → locked requirements.txt. Pip-native, minimal overhead.
  • PDM: Fast, PEP 621 native, lockfiles, scripts support.
  • uv: Ultra-fast from Astral, growing pyproject.toml integration.

Poetry suits many Flask projects due to extras and workspace support, though select based on your needs.

Prerequisites

  • Python 3.11+
  • Existing Flask app with requirements.txt
  • Backup your project

Step 1: Install Poetry

$ curl -sSL https://install.python-poetry.org | python3 -
# Example output (abbreviated):
Retrieving Poetry metadata
...
Poetry (version 1.8.3) successfully installed.
$ poetry --version
Poetry (version 1.8.3)
# If not found, add export PATH=\"$HOME/.local/bin:\$PATH\" to ~/.bashrc or ~/.zshrc, then source it.

Step 2: Initialize Poetry in Your Flask Project

$ cd /path/to/your/flask-app
$ poetry init --no-interaction  # Skips interactive prompts; outputs basic pyproject.toml

This creates basic pyproject.toml. Edit to set:

[tool.poetry]
name = "my-flask-app"
version = "0.1.0"
description = "Flask web application"
authors = ["Your Name <email@example.com>"]
packages = [{include = "app"}]  # Adjust to your src layout

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Step 3: Import Dependencies from requirements.txt

# Add all from requirements.txt (Poetry parses pins)
$ xargs poetry add < requirements.txt
# Note: Assumes simple lines without comments or extras; manual add for complex cases.

# Example requirements.txt:
# flask==3.0.0
# gunicorn>=21.0.0
# 
# Runs: poetry add flask==3.0.0 gunicorn>=21.0.0

Review pyproject.toml:

[tool.poetry.dependencies]
python = "^3.12"
flask = "^3.0.0"
gunicorn = ">=21.0"

Separate dev deps:

$ poetry add --group dev pytest black

Step 4: Generate Lockfile and Test Flask App

$ poetry lock  # Generates poetry.lock with resolved deps
$ poetry install  # Installs to project venv

# Test Flask
poetry run flask run
# Or: poetry run gunicorn app:app

Verify imports and app:

$ poetry run python -c "import flask; print('Flask:', flask.__version__)"
Flask: 3.0.0

$ poetry run python -c "import gunicorn; print('Gunicorn OK')"
Gunicorn OK

App starts with $ poetry run flask run; test endpoints.

Step 5: Update Scripts, CI/CD, and Cleanup

  • Update run.sh or Makefile: poetry run flask run
  • Docker: poetry export -f requirements.txt --output requirements.txt for prod if needed.
  • GitHub Actions:
    - name: Install Poetry
      uses: snok/install-poetry@master
    - run: poetry install --no-dev
  • Remove requirements.txt: git rm requirements.txt
  • Commit: git add pyproject.toml poetry.lock

Troubleshooting Common Issues

IssueFix
Version conflictspoetry lock --no-update
Extras (e.g., flask[async])poetry add 'flask[async]'
Editable installspoetry add -e .
Monorepo workspaces[tool.poetry.group.workspace.dependencies]
Slow resolutionpoetry lock --no-update; update Poetry
Binary deps fail (e.g. cryptography)Install system build deps (gcc, etc.) or use Docker
requirements.txt commentsStrip comments or add deps manually
Git/URL depspoetry add git+https://...@v1.0

Verify Migration

$ poetry show --tree  # Dependency tree
$ poetry check        # Validate pyproject.toml
# Example: ✓ pyproject.toml is valid

Conclusion

With this migration, your Flask app now uses pyproject.toml and poetry.lock for reproducible deployments. Next, consider adding [tool.poetry.scripts] for tasks like poetry run test.

Related:

Share your migration experience below!

Sponsored by Durable Programming

Need help maintaining or upgrading your Python application? Durable Programming specializes in keeping Python apps secure, performant, and up-to-date.

Hire Durable Programming