I have a module with a pretty regular layout, a main
function in a sacrypt
directory inside a __init__.py
file. Then, pyproject.toml looks like this;
[project]
name = "sacrypt"
version = "0.1.0"
description = "Cryptanalysis examples for SAC"
readme = "README.md"
requires-python = ">=3.13"
[project.scripts]
sacrypt = "sacrypt:main"
uv run sacrypt
, however, fails with:
error: Failed to spawn: `sacrypt`
Caused by: No such file or directory (os error 2)
I have tried changing it to a different name, as well as moving sacrypt
to src/sacrypt
to no avail. This is by the book following tutorials as well as the documentation. Any idea what is going on here or where I should poke to find the error? Running uv
with any amount of -v
is not giving any more information. Also, this is uv
version 0.6.9.
Update: As instructed in the comment, I have added a build system this way
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
And then issued uv build
. Still an error, this time different:
Traceback (most recent call last):
File "/home/jmerelo/Tutoriales/cemed-green-software/code/Python/.venv/bin/sacrypt", line 4, in <module>
from sacrypt import main
ModuleNotFoundError: No module named 'sacrypt'
Running it from the command line, or running tests, works fine.
It is actually easy.
So we have to add first the [build-system]
block for building - so give enough info for build-ing - which is necessary before a script can be called, and under [project.scripts]
we have to use the syntax:
<mycommandname> = "<module_or_file>:<invoked/entry_function_name>"
.
And call this defined command by:
uv run <mycommandname>
.
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project.scripts]
sacrypt = "main:main"
Starting with:
# start a project:
uv init sacrypt
Which generates the project structure:
sacrypt
├── README.md
├── main.py
└── pyproject.toml
We modify nano pyproject.toml
:
cd sacrypt
nano pyproject.toml
[project]
name = "sacrypt"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
to:
[project]
name = "sacrypt"
version = "0.1.0"
description = "Cryptanalysis examples for SAC"
readme = "README.md"
requires-python = ">=3.13"
dependencies = []
Then you added:
[project.scripts]
sacrypt = "sacrypt:main"
Which could not be run by:
$ uv run sacrypt
but rather invoking:
error: Failed to spawn: `sacrypt`
Caused by: No such file or directory (os error 2)
Somehow it couldn't build the package.
It seems one has to add the build information, like mentioned in this answer: https://stackoverflow.com/a/73066937/9690090 :
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
This info for building seems to be necessary.
The other point is - currently the only source file is main.py
.
The command must be of the form `commandname = "file_module_name:entry_function_name"
[project.scripts]
sacrypt = "sacrypt:main"
In our case, we have main.py
and a function def main(): print("Hello from sacrypt!")
.
So the correct version is:
[project.scripts]
sacrypt = "main:main"
So the entire pyproject.toml
is now:
[project]
name = "sacrypt"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project.scripts]
sacrypt = "main:main"
And then you can from inside the sacrypt
project folder run:
uv run sacrypt
And then you see:
% uv run sacrypt
Using CPython 3.12.9
Creating virtual environment at: .venv
Built sacrypt @ file:///Users/josephus/projects/python/sacrypt
Installed 1 package in 1ms
Hello from sacrypt!
And the folder structure is now:
sacrypt
├── README.md
├── __pycache__
│ └── main.cpython-312.pyc
├── main.py
├── pyproject.toml
├── sacrypt.egg-info
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ ├── dependency_links.txt
│ ├── entry_points.txt
│ └── top_level.txt
└── uv.lock
I have found this issue in astral-sh
's github which discusses the possibility to introduce such scripts - but it seems this is then solved.
are listed here: https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#creating-executable-scripts
using hatchling
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
using setuptools
[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"
using Flit
[build-system]
requires = ["flit_core >= 3.4"]
build-backend = "flit_core.buildapi"
or using PDM
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
They discuss in this issue that a
[build-system] ## doesn't work!!
requires = ["uv"] ## doesn't work!!
build-backend = "uv.api" ## doesn't work!! as of 20250322
would be nice - but this is not yet done!
I've tried them now - and can say in my macos
Python 3.12, only
setuptools
and PDM
work. all the other suggested ones didn't work (yet).