uv icon indicating copy to clipboard operation
uv copied to clipboard

Support .env-files

Open woutervh opened this issue 1 year ago • 96 comments

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

woutervh avatar Feb 15 '24 23:02 woutervh

Thanks for engaging with the project!

Specifically, you would like us to read .env files before every operation? Or something else?

zanieb avatar Feb 15 '24 23:02 zanieb

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)

woutervh avatar Feb 16 '24 11:02 woutervh

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.

woutervh avatar Feb 16 '24 11:02 woutervh

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!

zanieb avatar Jul 01 '24 21:07 zanieb

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.

dustalov avatar Jul 24 '24 23:07 dustalov

I am also migrating from pipenv which uses .env out of the box. It would be great if uv run could support this.

Count-Count avatar Aug 21 '24 04:08 Count-Count

Willing to consider this further, i.e., we'd read it in uv run only.

zanieb avatar Aug 21 '24 12:08 zanieb

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)

patrick91 avatar Aug 21 '24 12:08 patrick91

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.

lcoleman-scorability avatar Aug 22 '24 04:08 lcoleman-scorability

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.

simonw avatar Aug 24 '24 04:08 simonw

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.

LucasRoesler avatar Aug 29 '24 15:08 LucasRoesler

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.

kamuridesu avatar Aug 29 '24 23:08 kamuridesu

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.

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

Dufran avatar Sep 01 '24 06:09 Dufran

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.

sminnee avatar Sep 04 '24 00:09 sminnee

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?

TheRealBecks avatar Sep 09 '24 08:09 TheRealBecks

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.

gusutabopb avatar Sep 11 '24 03:09 gusutabopb

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 :-(

petermbauer avatar Sep 18 '24 06:09 petermbauer

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)?

cbrnr avatar Sep 18 '24 15:09 cbrnr

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.

zanieb avatar Sep 18 '24 15:09 zanieb

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 avatar Sep 20 '24 02:09 blakeNaccarato

@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.

woutervh avatar Sep 22 '24 00:09 woutervh

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.

sminnee avatar Sep 23 '24 02:09 sminnee

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:

seapagan avatar Sep 23 '24 09:09 seapagan

Unfortunately i have to use Windows so direnv won't work for me.

petermbauer avatar Sep 23 '24 09:09 petermbauer

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:

seapagan avatar Sep 23 '24 09:09 seapagan

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.

blakeNaccarato avatar Sep 25 '24 19:09 blakeNaccarato

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.)

charliermarsh avatar Sep 28 '24 22:09 charliermarsh

I think there are two options here:

  1. Respect .env in uv run (but not elsewhere). So, .env would be for providing runtime environment variables, but not for configuring uv itself.
  2. Respect .env everywhere.

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 (or UV_ENV_FILE) to override the file.
  • Add --no-env-file and UV_NO_ENV_FILE to disable it.

(In other words, I think it should be opt-out, not opt-in.)

charliermarsh avatar Sep 29 '24 17:09 charliermarsh

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?

command-tab avatar Sep 29 '24 18:09 command-tab

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.

charliermarsh avatar Sep 29 '24 18:09 charliermarsh