There's been a movement away from requirements.txt towards pyproject.toml. And commands like "uv add" and "uv install" take most of the pain of initializing and maintaining those dependencies.
Thanks, as mentioned, I'm not really a Python programmer so don't follow along the trends...
I tried to figure out why anyone would use pyproject.toml over requirements.txt, granted they're just installing typical dependencies and didn't come up with any good answer. Personally I haven't had any issues with requirements.txt, so not sure what pyproject.toml would solve. I guess I'll change when/if I hit some bump in the road.
1. You can differenciate between different dependency groups like build dependencies, dev dependencies, test dependencies and regular dependencies. So if someone uses some dependency only in dev previously you either had to install that manually or your requirements.txt installed it for you without you needing it.
2. It adds a common description for project metadata that can be used
3. Adds a place where tool settings like those of a linter or a formatter can be stored (e.g. ruff and black)
4. Its format is standardized and allows it to be integrated with multiple build tools, toml is a bit more standardized than whatever custom file syntax python used before
virtualenvs are great, but they're not great on their own. requirements.txt work sorta, but then any package with more than 50 requirements requires a non-trivial amount of manual labor to maintain. (Hell even 20 deps are a pain)
Astral uv and poetry both maintain the pyproject.toml for you -- and as a bonus, they maintain the virtualenv underneath.
Then for the complete python newbs, they can run 'uv sync' or 'poetry install' and they don't have to understand what a virtualenv is -- and they don't need root, and they don't have to worry about conflicts, or which virtualenv is which, etc.
So the simple case:
mkdir test
cd test
# init a new project with python 3.13
uv init -p 3.13
# Add project deps
uv add numpy
uv add ...
# Delete the venv
rm -rf .venv
# reinstall everything (with the exact versions)
uv sync
# Install a test package in your venv
uv pip install poetry
# force the virtualenv back into a sane state (removing poetry and all it's deps)
uv sync
# update all deps
rm uv.lock
uv lock
Now cat your pyproject.toml, and you'll see something like this:
[project]
name = "test"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"numpy>=2.2.5",
"pillow>=11.2.1",
"scipy>=1.15.2",
]