uv
uv copied to clipboard
Support .env-files
In my workflow I make heavy use of env-files.
several tools support .env out of the box:
- docker / docker-compose
- just (https://just.systems/man/en/chapter_26.html?highlight=env#settings)
- easy to support in makefiles
- easy to support in python-apps
It would be nice if uv could support .env-files in the $CWD or parent-dirs. see https://crates.io/crates/dotenv
Thanks for engaging with the project!
Specifically, you would like us to read .env files before every operation? Or something else?
Specifically, you would like us to read .env files before every operation? yes.
pip supports a config-file pip.ini / pip.conf all those values in that config-support can also be set as environment-variables
I have not yet seen a reference that uv pip supports such config-file or these envvars,
but many times I set such project-specific pip-envvars, the same for twine.
some examples:
- PIP_EXTRA_INDEX_URL
- RUFF_CACHE_DIR
- TWINE_USERNAME
- TWINE_REPOSITORY_URL
<project-dir>
.env
.venv/
docs/
src/
tests/
so my request is to support .env-files in $CWD, and optionally in parent-levels (e.g in just this is configurable)
I always try to setup projects in an isolated way:
<project-dir>
.env
.venv/
docs/
src/
tests/
var/cache
var/cache/ipython
var/cache/pytest
var/cache/python
var/cache/ruff
var/cache/sphinx
var/cache
var/log
var/tmp
to make ruff use the my .env to read RUFF_CACHE_DIR, I currently have to install ruff in the .venv and use python-entrypoint to execute ruff (slowing things down)
I use my package https://github.com/libranet/autoread-dotenv to read the .env via sitecustomize-hooks, so the env-vars become available for any python-generated entrypoint.
I'm going to mark this as not-planned for now. We may revisit in the future. If people have additional use-cases or thoughts please feel free to share!
I have a similar use case.
I am launching machine learning demos for students, and I am currently using Pipenv which loads environment variables from a file named .env. That file contains variables like DO_NOT_TRACK=1 and HF_HUB_DISABLE_TELEMETRY=1 which are applied for all the commands I run via pipenv run.
As a workaround, I can define them in my shell profile, but it would be great to have it natively supported by uv.
I am also migrating from pipenv which uses .env out of the box. It would be great if uv run could support this.
Willing to consider this further, i.e., we'd read it in uv run only.
This might of inspiration, PDM supports something like this: https://pdm-project.org/en/latest/usage/scripts/#env_file
I've personally used this as a way to not use tools like dotenv, since I usually need them locally and not on production 😊 (plus is one less thing to worry about)
We would really love teh ability to load from a .env file for the same reason as above - we use a lot of our applications configuration in .env files.
Supporting this in uv run seems like it could be really useful to me. When I'm working with Django I often have it pick up os.environ["..."] for things like API keys needed by my application. uv run ./manage.py runserver to pick up those from a .env file could be a really nice pattern.
I am also interested in the uv run support. I am coming from Poetry and currently use this plugin to achieve the same flow to pick up env variables from the .env at the project root.
I think it would be useful to have a flag like --env-file or some section in the config file like PDM does.
But why limit it to uv run only? uv uses a set of environment variables in place of command line arguments, that way you can use different definitions for uv depending on your environment. I personally think it would be useful for situations like when you use a custom packages index for example.
I am also interested in the
uv runsupport. I am coming from Poetry and currently use this plugin to achieve the same flow to pick up env variables from the.envat the project root.
Hi, I was also migrating from poetry to uv, and currently use taskfile to handle .env variable passing to uv run
Example of the taskfile
version: "3"
dotenv: [".env"]
tasks:
manage:
cmds:
- uv run ./backend/manage.py {{.CLI_ARGS}}
and then i can run stuff like
task manage -- makemigraitons
task manage -- shell_plus etc
Another user-case: I supply environment variables to my dev server with a .env file. I've been using poetry run bin/serve-dev to start things with a dotenv loading plugin for poetry.
uv run bin/serve-dev auto-loading my .env file would be nice, but to be honest uv run --env-file .env bin/serve-dev is fine too, if you want to limit the blast radius of this change.
After the migration from pipenv to uv our local Ansible environments are now broken as uv does not read the .env file.
@zanieb @charliermarsh After reading this thread it looks like that missing feature is a real showstopper?
Here's a non-Python example: Node JS added native support to this feature in September 2023 (changelog) and it has been supported by Bun/Deno for a while now.
My use case is to use a separate project-specific Conan Local Cache when entering the respective venv. This simply means setting the CONAN_USER_HOME env var to the venv path with source .venv/bin/activate.
Currently, this is done by fumbling this into the generated activate/deactivate scripts. These scripts also vary between the Python versions so this also needs to be tested and updated for new Python versions :-(
I'm not sure if my use case is related, but I really enjoy pyenv automatically activating a specific venv if it finds a .python-version file in the directory. I guess the same can be achieved with .env, but maybe there is already a way to use uv to auto-activate envs? Or is this not necessary anymore with uv run (sorry for my ignorance, I haven't really used uv much yet)?
Or is this not necessary anymore with uv run (sorry for my ignorance, I haven't really used uv much yet)?
It shouldn't be needed if you use uv run, though it's a bit more nuanced than that. Feel free to open a new issue if you run into problems there.
I like Brett Cannon's and Jeff Triplett's takes on .env files, which identify the orthogonal purposes of using such files for configuration and for secrets. They also identify the issue with the lack of a standard of .env files, e.g. path separator variation and other nuances.
Brett posed the question, could we standardize on TOML for this? I think if uv picks this up, it could be done in stages, supporting .env today but with no promises on the unstandardized format, then eventually incorporating a more opinionated take inside pyproject.toml in a subtable of tool.uv.
Secrets management is it's own beast, of course.
The upside to uv tackling lockfiles is the standards discussion on that is already pretty mature, but there's no clear consensus on standardizing something for .env, so maybe that's a bridge too far.
@blakeNaccarato IMHO it is widely understood that .env-files should have a bash-compatible syntax. Besides that, there should not be anything language or tool specific.
Brett posed the question, could we standardize on TOML for this?
The great thing about ruff is that it's essentially a drop-in replacement for pylint and other tools you were probably using before.
Doing the same with .env files would be a DX win.
Championing an emergent new format would be an interesting idea, as a separate and second step, but until it becomes comparable to .env in terms of adoption, it seems like a DX loss to deprecate .env.
I use direnv for this exact use-case. It is installed as a global binary on pretty much any OS, then activates any .envrc or optionally also .env when the folder is entered. This is a mature tool that does exactly this one job very well, with the bonus of not being restricted to only Python as it works on any folder, anywhere.
The big plus for me is that you need to explicitly enable the file for each folder (once off check) so it will not activate any random file you get in a cloned repo.
uv doesn't need to do absolutely everything :wink:
Unfortunately i have to use Windows so direnv won't work for me.
Unfortunately i have to use Windows so direnv won't work for me.
I haven't tried it myself, but there is a windows download using winget offered, even though it does say only '*nix' compatible on their github 🤷♂️. Ignore me if you've tried this and it didn't work :grin:
EDIT: people have used it with varying degrees of success, this gist has a walk-through
EDIT 2: I had a bit of time so I booted into windows, updated powershell as it doesn't work in the default version, traced and sorted the issues it has by default and jumped through hoops (needs 3 badly documented env var set). Then came to the conclusion it is totally borked under windows. Sorry, carry on :grin:
I wrote an isolated script for syncing .env with a tool.dev.env table in pyproject.toml (by default, but it's configurable via CLI) that you can run in a shell profile or in your shell initialization flow. It's barebones and only supports environment variables hard-coded in your pyproject.toml (e.g. no secrets), but I'm sure someone could extend it into a full utility. See also dump-env for a feature set supporting secrets and .env templating.
I’m supportive of adding this to uv run. It would also enforce that the point is not to configure uv but to configure the underlying commands.
(I think it’s not too difficult to add and there’s clearly a lot of demand.)
I think there are two options here:
- Respect
.envinuv run(but not elsewhere). So,.envwould be for providing runtime environment variables, but not for configuring uv itself. - Respect
.enveverywhere.
My inclination is to do the former (and I think we could get consensus on + ship that quickly). The downside is that you still need to provide UV_-prefixed environment variables (which could include credentials) through some other mechanism.
Maybe we start with (1) and we can always expand to (2) if it's well-motivated.
If we do (1), my preference would be:
- Always read
.env - Allow users to pass
--env-file(orUV_ENV_FILE) to override the file. - Add
--no-env-fileandUV_NO_ENV_FILEto disable it.
(In other words, I think it should be opt-out, not opt-in.)
For my use cases, option 1 is sufficient. I only need .env files to be loaded at uv run time, and I would prefer uv run do so by default, which is equivalent to pipenv's pipenv run behavior. Offering opt-out flags seems like a good move.
With regard to credentials, which is often my reason for using a .env file in development, could you explain more about this statement?
My inclination is to do the former (and I think we could get consensus on + ship that quickly). The downside is that you still need to provide UV_-prefixed environment variables (which could include credentials) through some other mechanism.
In that scenario, if I had a development credential that was previously kept in an un-committed/.gitignored as, say, GOOGLE_API_KEY=123456 would I need to prefix GOOGLE_API_KEY with UV_ for uv to load it? Or are you talking only about env vars for configuring uv?
Or are you talking only about env vars for configuring uv?
I'm only referring to these. In other words, we'd pass the environment variables onwards to whatever uv run runs, but we wouldn't use them within uv itself.