Open woutervh opened 1 week ago
We don't read configuration for uv itself from .env
files, the variable are passed to the subcommand called by uv run
Hooking on to this, since I'm also testing .env
support and am experiencing inconsistencies. I'm not sure whether I might be misunderstanding this feature.
$ uv version
uv 0.5.1 (Homebrew 2024-11-08)
From the documentation and https://github.com/astral-sh/uv/pull/8263 I expected that uv run [COMMAND]
would export the env vars from <project_root>/.env
if that file exists and pass them to the [COMMAND]
(I assume that this command can be any shell command).
I've created a fresh project, added a .env
and a simple script:
uv init test
cd test
cat <<EOF > .env
FOO=bar
EOF
cat <<EOF > test.py
import os
print(os.environ.get('FOO'))
EOF
The steps I've taken that I had issues with
uv run -- echo $FOO
displays an empty lineuv run --env-file .env -- echo $FOO
displays an empty line (contrary to what the docs indicate here at https://docs.astral.sh/uv/configuration/files/#envuv run test.py
displays None
uv run --env-file .env test.py
displays bar
as I would have expected for all of the aboveFurthermore, I tried adding a private index (which is what led me down this path) by adding to my pyproject.toml
dependencies = [
"secret-project==1.2.3"
]
[[tool.uv.index]]
name = "secret-project"
url = "https://secret-project.com/simple"
and the credentials to my .env
:
UV_INDEX_SECRET_PROJECT_USERNAME=myusername
UV_INDEX_SECRET_PROJECT_PASSWORD=mypassword
(as the previous steps created the venv I deleted it and cleaned the cache before moving on: rm -rf .venv && uv cache clean
)
uv sync
fails with a error: Failed to prepare distributions
caused by 401 authentication error when trying to fetch secret-project
- I would have really liked this to work out of the box, but expected this to fail due to how the .env
support was described.uv run uv sync
and uv run -- uv sync
both fail for the same reason as 1.
. which I didn't expect.uv run
fails for the same reason as 1.
and 2.
uv run --env-file .env
creates the venv successfully and install secret-project
from the private index. Note that if you had run uv run --env-file .env -- echo $UV_INDEX_SECRET_PROJECT_USERNAME
instead, it would have also successfully created the venv, but not display the env var. So it seems to me that the env vars aren't passed to the subprocess as described and uv run
doesn't load .env
by default. Also it seems I cannot install/update my deps with uv sync
in my case, but only with the workaround of using uv run --env-file .env
to leverage it's automatic syncing.
Additionally, I would have expected uv sync
to respect .env
as well. Since I am defining the index in the project's pyproject.toml
, I would assume that most people would like to define their credentials in the .env
along with other their tokens. Just my two cents.
Please, let me know if what I described above is actually working as intended and I'm just misusing uv
.
Thanks for your comment. A few clarifications:
uv run --env-file .env -- echo $FOO
can never work -- it's a mistake in the docs. Your shell evaluates $FOO
there before it's passed to uv, so it's just not possible for uv to replace it in that context..env
files by default. You must pass --env-file
. (Do the docs say we read them by default somewhere?).env
file only affects the command that uv run
runs. It doesn't affect uv itself. We may expand that in the future, but the intent in this initial implementation is that uv itself shouldn't be configured by .env
files. So things like UV_INDEX_SECRET_PROJECT_PASSWORD
wouldn't have any effect, but something like configuring your database port via a PORT
variable would.Thanks for the quick response.
We don't load .env files by default. You must pass --env-file. (Do the docs say we read them by default somewhere?)
In https://github.com/astral-sh/uv/pull/8263 which is referenced in the changelog it says:
The behaviour is as follows:
- uv run file.py executes file.py using the .env (if it exists).
- [...]
- uv run --no-env-file file.py skips reading the .env file.
The docs say:
To disable dotenv loading (e.g., to override UV_ENV_FILE or the --env-file command-line argument), set the UV_NO_ENV_FILE environment variable to 1, or pass the--no-env-file flag to uv run.
Which I interpreted as loading is enabled by default, so I can disable it like this, but I realize I probably didn't read that sentence carefully enough.
And in the linked PR's thread there are talks about this being an opt-out feature.
So all of this made me assume it would load .env
files by default and I had to opt-out via UV_NO_ENV_FILE
or --no-env-file
. Having to specify --env-file
or UV_ENV_FILE
makes it opt-in, doesn't it?
The .env file only affects the command that uv run runs. It doesn't affect uv itself. We may expand that in the future, but the intent in this initial implementation is that uv itself shouldn't be configured by .env files. So things like UV_INDEX_SECRET_PROJECT_PASSWORD wouldn't have any effect, but something like configuring your database port via a PORT variable would.
Thanks for clarifying. Having read this, I still don't understand why uv run --env-file .env -- uv sync
wouldn't work, isn't uv sync
the command being run by uv run
and should be affected by the .env
loading? Or put differently, why would uv run
's auto-sync work, but not the one invoked by me manually in uv run --env-file .env -- uv sync
?
Thanks @laermannjan. So I think the docs are generally correct -- #8263 initially merged with the behavior as opt-out, but we changed it to opt-in prior to releasing. I can see how it's confusing.
Having read this, I still don't understand why
uv run --env-file .env -- uv sync
wouldn't work...
I think I would expect this to work. Let me try it.
In my testing uv run --env-file .env -- uv sync --verbose
does work as expected. I set UV_INDEX_URL=https://test.pypi.org
in .env
, and the verbose logging indicates that it read from the Test PyPI.
uv --version uv 0.4.30 (61ed2a236 2024-11-04)
Testing .env-file support, but I can't get this to work. Using private indexes still remains painful.