Beware the thrill of ephemeral joys

In some cases we need to run a tool for some purpose and we ask ourselfs whether it is necessary to actually install the tool in our environment.
For such cases uv offers the possibility to use separate ephemeral environments to install the dependencies.

Running tools in ephemeral environments is in some cases very useful. But it also has some caveats!

Some tools generate scripts that refer to other parts of the environment (e.g. by hard coding the path to the python executable). One of those tools is mkzeoinstance.

mkzeoinstance generates (among other files) the scripts zeoctl and runzeo with the variables PYTHON and ZODB3_HOME pointing to the executable python and to the directory site-packages respectively.

When running mkzeoinstance in an ephemeral enviroment (e.g. with uv run --with or with uv tool run) both the executable python and the directory site-packages are in an ephemeral environment in the cache.
Those generated scripts will only work until (for whatever purposes) one decides to clear the cache (uv cache clean). Clearing the cache removes the linked executables and the site-packages.

Then the scripts zeoctl and runzeo become unusable. (Unless you manually change those paths to point to an existing environment)

Use ephemeral environments only if you know that your tools do not generate code linked to files or directory in the ephemeral environment.

To reproduce this see the code below:

$ uv init --bare ~/myproject --python 3.12
$ cd myproject/
$ uv cache clean
# both `uv run --with` and `uv tool run` use ephemeral environments
# uv run --with zope.mkzeoinstance mkzeoinstance zeoserver 127.0.0.1:8100
$ uv tool run --from zope.mkzeoinstance mkzeoinstance zeoserver 127.0.0.1:8100
# both `zeoctl` and `runzeo` have hard coded paths
$ grep --color "^PYTHON=.*\|^ZODB3_HOME=.*" zeoserver/bin/zeoctl

PYTHON="/home/map/.cache/uv/archive-v0/r9IfKh4JjXKa2yqpIkysS/bin/python"
ZODB3_HOME="/home/map/.cache/uv/archive-v0/r9IfKh4JjXKa2yqpIkysS/lib/python3.13/site-packages"
$ ./zeoserver/bin/runzeo --version
5.2

$ uv cache clean
Clearing cache at: /home/map/.cache/uv
Removed 2658 files (54.7MiB)

# after clearing the cache the python executable is not found
$ ./zeoserver/bin/zeoctl --version
./zeoserver/bin/zeoctl: 21: exec: /home/map/.cache/uv/archive-v0/r9IfKh4JjXKa2yqpIkysS/bin/python: not found

If you want the generated scripts point to the current actual environment, you need uv run (not uv run --with nor uv tool run) to ensure that the command runs in the actual enviroment. And of course you need to previously uv add the tool (or uv pip install if you don't want/need it as a dependency in your pyproject.toml).

$ uv init --bare ~/myproject --python 3.12
$ cd myproject/
$ uv cache clean
$ uv add zope.mkzeoinstance
#  uv venv && uv pip install zope.mkzeoinstance
$ uv run mkzeoinstance zeoserver 127.0.0.1:8100

$ grep --color "^PYTHON=.*\|^ZODB3_HOME=.*" zeoserver/bin/zeoctl
PYTHON="/home/map/myproject/.venv/bin/python3"
ZODB3_HOME="/home/map/myproject/.venv/lib/python3.13/site-packages"

$ ./zeoserver/bin/zeoctl --version
5.2

$ uv cache clean
$ ./zeoserver/bin/zeoctl --version
5.2

$ uv run python -c "import os,sys; print(os.path.realpath(sys.executable))"
/home/map/.local/share/uv/python/cpython-3.13.4-linux-x86_64-gnu/bin/python3.13