pydantic / pydantic-settings

Settings management using pydantic
https://docs.pydantic.dev/latest/usage/pydantic_settings/
MIT License
643 stars 65 forks source link

`env_prefix` falls back to env vars without prefix #441

Open hofrob opened 1 month ago

hofrob commented 1 month ago

Using my example from #437: https://github.com/hofrob/pydantic-settings-env-prefix

If you uv run hello the result is:

hello='ABC'

This value is coming from the first line in .env: HELLO=ABC

I don't think the intention of env_prefix is to just fall back to whatever env var it can find that matches the variable without the prefix. If you have nested or complex settings with multiple API keys managed via different env_prefix values, you'll not want to use an API key with the wrong service. I'd consider this API key compromised.

See also this comment: https://github.com/pydantic/pydantic-settings/issues/437#issuecomment-2399393932

ericchansen commented 2 weeks ago

I'm confused about env_prefix. When I use env_prefix, the original env var gets ignored. It will only load an env var if it it matches the name with the env_prefix.

hofrob commented 2 weeks ago

Yes, it works when there an env var exists with the prefix. But I think it should stay empty if it does not find the env var + prefix as opposed to fall back to an env var without the prefix.

ericchansen commented 1 week ago

Thanks! I thought that setting env_prefix acted like an alias, such that in your example, either HELLO or SOME_PREFIX_HELLO should work. I guess the documentation is confusing me. It would be nice to get a clear answer from the devs as to what the intended behavior is.

I'm currently struggling with pydantic as well, but it seems like we're observing different behavior. In my use case, I was expecting the env var to get loaded from the raw variable or the variable name with the env_prefix (in other words, like I described above, where it would work like an alias). However, it ONLY works for the variable name with the env_prefix (the raw variable name doesn't work, unlike alias behavior). @hofrob, does this sounds like the opposite problem that you're having?

EDIT: I'm learning more. It seems the behavior is different if there's a default value. If there is a default value, then it will not check the variable name without the env_prefix. If there isn't a default value, it will check the variable name without the env_prefix.

I think the order of priority is:

1. env_prefix + var 2. default 3. var