> My build step is then just python3 -m build. This populates the dist/ directory with everything needed to install and run the project on a server.
> ...
> Just python, pip, rsync, and systemd are enough to build and deploy a production ready python service.
It should be noted here that, while it's a small, semi-standard tool under the PyPA umbrella, `build` is not part of the standard library. It must be installed separately, and thus should have been listed as one of the tools used. (On the other hand, I don't really see what any of this has to do with systemd; it can equally well be made to work on Windows or on non-systemd Linux distros.)
> First of all, I have nothing against Poetry, uv, pdm, and others. I just prefer not to learn more tools, more configurations, and use only standardized built-in tools wherever possible. So as a result, I use setuptools only.
`setuptools` has the advantage of preferential treatment within the ecosystem (e.g., at least transitionally, a `[build-system]` table like the one shown could be omitted completely, as Setuptools would be assumed by default; and virtual environments used to bootstrap Setuptools as well as Pip by default.
However, with current versions of Pip (and Python, thus venv from the standard library), as well as with `build`, the default behaviour is to create an "isolated environment" for building (even, AFAIK, if the project is already containerized - how would the tools know, after all?). This entails creating a new venv and installing Setuptools therein - using Pip to find the latest version (subject to any version constraints specified in pyproject.toml) on PyPI. In theory, packages that Pip downloads from PyPI are cached; but even when Setuptools hasn't released a new version since the last build, any number of things could defeat that caching scheme.
This is important because, while Setuptools works and it succeeds in making the simple cases simple (including with the new pyproject.toml-powered approach), it's a massive boat-anchor for most projects that use it. The wheel size approaches 1MB for a possibly-transient download used just to "build" your project - which in most cases doesn't even involve a compilation step (actually telling Setuptools to run compilers requires a separate setup.py file, even with pyproject.toml) but just moves some files around and creates a zip archive - and which in most cases is itself quite a bit smaller. It got to this size, effectively, by starting its life as a decades-old attempt at a full project management toolchain, and then collapsing under the weight of deprecations and backwards-compatibility hacks (including, now, the need to vendor `distutils` since that was removed from the standard library in 3.12).
Notably, originally setup.py was intended to be run directly chosen by the user, but now Setuptools does magic to spawn a new process (IIRC), run it with very specific arguments and collect the results somehow. Meanwhile, even the most conservative attempts to remove old deprecated functionality (such as the ability to run `setup.py test` manually, even though it has nothing to do with the modern Setuptools workflow and everyone uses Pytest and invokes that directly nowadays) have caused huge breakages in the ecosystem and embarrassing rollbacks (see https://github.com/pypa/setuptools/issues/4519 as a starting point), even for pure-Python projects where that functionality was grossly unnecessary and wasn't actually being used (notably: Requests - https://github.com/psf/requests/issues/6775 - and Celery - https://github.com/celery/celery/issues/9157 ).
1 comment
[ 2.8 ms ] story [ 11.9 ms ] threadIt should be noted here that, while it's a small, semi-standard tool under the PyPA umbrella, `build` is not part of the standard library. It must be installed separately, and thus should have been listed as one of the tools used. (On the other hand, I don't really see what any of this has to do with systemd; it can equally well be made to work on Windows or on non-systemd Linux distros.)
> First of all, I have nothing against Poetry, uv, pdm, and others. I just prefer not to learn more tools, more configurations, and use only standardized built-in tools wherever possible. So as a result, I use setuptools only.
`setuptools` has the advantage of preferential treatment within the ecosystem (e.g., at least transitionally, a `[build-system]` table like the one shown could be omitted completely, as Setuptools would be assumed by default; and virtual environments used to bootstrap Setuptools as well as Pip by default.
However, with current versions of Pip (and Python, thus venv from the standard library), as well as with `build`, the default behaviour is to create an "isolated environment" for building (even, AFAIK, if the project is already containerized - how would the tools know, after all?). This entails creating a new venv and installing Setuptools therein - using Pip to find the latest version (subject to any version constraints specified in pyproject.toml) on PyPI. In theory, packages that Pip downloads from PyPI are cached; but even when Setuptools hasn't released a new version since the last build, any number of things could defeat that caching scheme.
This is important because, while Setuptools works and it succeeds in making the simple cases simple (including with the new pyproject.toml-powered approach), it's a massive boat-anchor for most projects that use it. The wheel size approaches 1MB for a possibly-transient download used just to "build" your project - which in most cases doesn't even involve a compilation step (actually telling Setuptools to run compilers requires a separate setup.py file, even with pyproject.toml) but just moves some files around and creates a zip archive - and which in most cases is itself quite a bit smaller. It got to this size, effectively, by starting its life as a decades-old attempt at a full project management toolchain, and then collapsing under the weight of deprecations and backwards-compatibility hacks (including, now, the need to vendor `distutils` since that was removed from the standard library in 3.12).
Notably, originally setup.py was intended to be run directly chosen by the user, but now Setuptools does magic to spawn a new process (IIRC), run it with very specific arguments and collect the results somehow. Meanwhile, even the most conservative attempts to remove old deprecated functionality (such as the ability to run `setup.py test` manually, even though it has nothing to do with the modern Setuptools workflow and everyone uses Pytest and invokes that directly nowadays) have caused huge breakages in the ecosystem and embarrassing rollbacks (see https://github.com/pypa/setuptools/issues/4519 as a starting point), even for pure-Python projects where that functionality was grossly unnecessary and wasn't actually being used (notably: Requests - https://github.com/psf/requests/issues/6775 - and Celery - https://github.com/celery/celery/issues/9157 ).
Setupto...