where the first command will apply the suggested changes to .venv from this PEP and override any previous use of venv with this option. The second will not touch .venv. With this option, these two statements can be executed in either order, and have the same effect.
I would say that invoking could be enough if the workflow tool made it clear-- whether via docs or something --that it was going to overwrite another tool.
I honestly put this in for you all since you seemed concerned about tools trampling over some .venv redirect file uv wrote. I can also take it out and let user complaints handle the issue when a tool goes trampling over a .venv redirect file when they shouldn’t.
For us, the main concern is not that someone will overwrite it, it’s that uv will overwrite it from another context with a different “current” environment. We don’t want to prevent that, we want to be able to fix it up without needing user intervention. We can document this, but let me elaborate on why we’d prefer not to have the ownership restriction:
Let’s say you’re sharing the project directory between a container and your host, and you’re using uv’s feature that puts the virtual environment in the cache. The path to the cache in the container can differ from the host (regardless of if it is shared or not). We can’t assume it will be invalid (thereby allowing us to just clobber it). If the target exists, it may point into a uv cache, but not the one configured in the current context, so we cannot reliably determine ownership from the path without heuristics.
Since the PEP does not impose this ownership restriction on .venv directories, symlinks or junctions, would it be simpler not to impose it on redirect files either?
Sure. Once again, this clarification is only in there because uv asked for it. I personally don’t think it’s necessary, but it can be explicitly extended to the path in the .venv redirect file if you want.
I also didn’t expect it to be necessary but when working on centralised environment support I found that many tools, including VS Code, currently misbehave if .venv is a junction or symlink which is why it made me think that having this codified would help improve that situation.
I don’t necessarily think this needs to be explicit for redirect-file targets; I was mostly just curious whether the difference in wording was intentional.
tox and virtualenv ship experimental support for the .venv redirect file of the current draft, on by default. We mark it provisional; while the PEP stays a draft, we may change it in a minor or patch release, backward incompatible changes included, to follow the spec.
virtualenv 21.12.0 and later point the .venv redirect file in the parent folder at each environment they create. After creating <dir>/<name>, virtualenv writes <name> into <dir>/.venv, so tools pick the environment you created last. It leaves a .venv directory or symlink alone. It replaces an existing redirect file when the target’s pyvenv.cfg carries the virtualenv key, and keeps one that another tool or the user wrote, even when its target does not exist on this machine. Pass --no-venv-redirect to turn it off. Docs
From tox 4.64.0 on, tox writes the redirect file next to its configuration at the end of each run, naming the environment you edit code against. It prefers an environment named dev, then one that installs the project in develop mode. Without either, it takes the first entry of env_list. Set venv_redirect_env to pick another environment, or venv_redirect = false to turn it off. The redirect file holds a relative path with forward slashes (.tox/dev), so you can commit it, as the PEP suggests for a tox dev environment. tox treats a redirect file as its own when the target sits inside its work directory or is one of its environments, and leaves any other one alone. Docs
A redirect file holds a path and nothing about its writer, so both tools judge ownership by the target, as Brett suggested to Tomasz. Each knows its own environments. We would keep the check if the PEP drops the SHOULD NOT overwrite rule.
The PEP rules an empty redirect file invalid, so tox deletes the redirect file while it rebuilds the environment it names on --recreate, and writes it back when the run ends. The PEP could say whether readers should expect a redirect file to vanish for that window.
Hang on - so that means that if I create a virtual environment using virtualenv foo in some work directory (specifically not a Python project directory) then virtualenv will arbitrarily decide that this is intended as the “default” virtual environment for that directory and create a .venv file? That seems to me to be at odds with the idea that it should be cheap to create “throwaway” virtual environments as needed.
That’s not at all how I expected PEP 832 to work. I’m a strong -1 on this being the behaviour.
At the very least, can PEP 832 make it clear that the stdlib venv module must not work like this, and creating a .venv redirect file is the responsibility of higher level tools? I’d argue that virtualenv is in the same position as venv, being a low-level environment creation tool, but I guess that’s a tool UI decision and if virtualenv wants to leave being the low-level venv creation tool to venv, then that’s their choice.
If I use tox at all, I end up with a .venv redirect? And it uses the last run, even in parallel mode where that’s not deterministic? That all makes no sense. Flask uses uv to manage the development environment, it uses tox only to manage separate test environments. This would break every Pallets and Pallets-Eco project workflow silently on upgrade, unless every project remembered to disable the new feature. Suddenly, every maintainer’s IDE would point to a random tox env instead of the main uv env. Why not only do this with tox devenv, that signals deliberately using it to create a development environment, not a test env.
Understood, that’s a tool UI decision (I’d prefer a flag to opt in for a low-level tool like virtualenv, but that’s just my opinion). I’ll note that while --no-venv-redirect exists, if the user sets this in a config file there’s no command line option to re-enable it for a single invocation.
Also, I’d much prefer it if virtualenv only write .venv if the directory contained a pyproject.toml file, indicating that the environment was associated with a project, where “discovering the default environment” makes sense. But virtualenv UI discussions should probably happen elsewhere - should I open an issue on the tracker?
My main point here was that I think it’s important to emphasise in the PEP that setting .venv is intended for project management tools, and not part of the basic (low level) mechanism for creating a venv.
Not everyone uses the devenv feature, some people use a tox dev env instead, that’s prioritized. Though on reflection I do agree, if that’s not present likely the env picked should be stable or just not created.
For now I think here might be better, as it’s important we clarify expectations on how the feature works so that the PEP can reflect that.
I’d be interested to know why you thought that it was appropriate for virtualenv to create a redirect file like this. My reading of the PEP didn’t give me that impression at all - the redirect file was for the user, or tools that manage a project directory, to create. And I don’t see virtualenv (or uv venv outside a project directory, or python -m venv) as being that type of tool.
Using the .venv or venv always felt arbitrary to me. I do create occasionally environments with different names, and would be nice for tools/IDEs to automatically pick that up. E.g. if I do:
virtualenv magic
and there’s no other venv in the folder setting as hey use this felt like a good feature, at least for how I use virtulaenv.
virtualenv 21.12.1 writes the redirect when the parent folder holds a pyproject.toml and has no .venv yet, so virtualenv foo in a scratch folder leaves that folder alone. --venv-redirect writes it in any folder, --no-venv-redirect skips it, and a flag on the command line now beats the config file and the environment variable in either direction.
tox 4.64.2 points the redirect at a deliberate development environment: the one in venv_redirect_env, else one named dev, else the first with a develop install. A project that uses tox for tests alone gets no file. tox devenv writes it for the environment it creates, and tox stops virtualenv from writing a redirect of its own beside tox environments. On the earlier question, tox did not pick the last environment that ran; it fell back to the first env_list entry, which had the same problem.
There’s no changes being proposed to the venv module in this PEP on purpose as that forces this PEP on the SC.
As I said, I put that in for uv, so since you all don’t seem to want it (at least as phrased), I’ll just remove it.
That probably is more of a bug report on the appropriate VS Code extension. I will also say I have gotten private feedback to not allow symlinks or junctions specifically because if you don’t plan for it then things can go awry.
Nope.
As I said above, I didn’t propose any changes to the venv module on purpose. I also don’t feel comfortable having a PEP restrict the venv module’s UX like that (much like previous PEP feedback I have received was to not mandate what tools do).
That’s hard to crisply specify and not something I want to wade into. If a tool doesn’t do something that users want then that seems like feedback for the tool and not some restriction based on some tool type classification that should be in a PEP.
I find the PEP’s agnosticism on logical vs physical paths to be inconsistent with the allowance for relative paths in the .venv redirect file, because .. is ambiguous in the presence of symlinks (see Lexical File Names in Plan 9 or Getting Dot-Dot Right).
Relevant passages:
This PEP makes no judgment whether .venv is a physical or logical path to a directory containing a virtual environment, nor whether logical paths should be resolved to their physical equivalent before use.
And:
The line in the .venv redirect file MUST point to a directory […]
The path MAY be relative
Ideas:
Require that relative paths in venv redirect files are to be interpreted relative to the physical path. (I haven’t thought too hard about this, but I don’t think anything else is reasonable behavior.)
We could disallow .. in relative paths.
Continue to express no opinion at the risk of tools handling this inconsistently.
Separately, if there are conversations about extending this to be able to support other types of environments (I see mention of Conda in the PEP), I’d be interested in discussing how this could support Nix dev shells as well.
There’s a reason why some asked to ban logical/symlink paths.
The physical path of what? Relative paths are based on the location of the .venv redirect file. Are you worried about people using a symlink for the redirect file itself?
Sorry, can’t as that’s needed for monorepos and other setups.
Probably this. The best I can do is give guidance as to what to do if the .venv redirect file itself is a symlink (and I would probably say “you SHOULD NOT use a logical path for the .venv redirect file itself when it contains a relative path due to ambiguity of whether the logical or physical path should be used for resolving the relative path”).
See the history in this topic as well as others related to WSP.
This PEP is explicitly only about virtual environments. Unless you’re asking about getting the venv module to support them (which would be off-topic for this PEP), it seems out-of-scope.
As I understand it @jfly means the physical path of the directory containing .venv. For example, if /home/alice/project is a symlink to /home/alice/code/project, their suggestion would make ../env in /home/alice/project/.venv refer to /home/alice/code/env, rather than /home/alice/env. You can hit this situation regardless of if .venv is itself a symlink.
I think the suggested approach (“Require that relative paths in venv redirect files are to be interpreted relative to the physical path.”) would make the most sense for us too.
We’d be more than happy if .venv had to be either a physical/logical path to a directory XOR a redirect file and never a symlink to a redirect file. The main point of .venv a a redirect file in our eyes is to cater for the rare situation where a symlink (or something of that nature) isn’t possible.
But doesn’t that depend on when/if you resolve the symlink? If you do the resolving of the relative path purely based on the text of the base symlink path then you get the outcome you’re expecting.
I’m fine with that as it’s cheap enough of a file to create and update.
Here’s a proposed change. This capture what you’re after @kramkowski and @jfly ?
diff --git i/peps/pep-0832.rst w/peps/pep-0832.rst
index b26a876c..ef7b9f3b 100644
--- i/peps/pep-0832.rst
+++ w/peps/pep-0832.rst
@@ -88,14 +88,14 @@ logical paths should be resolved to their physical equivalent before use.
Instead of a directory containing a virtual environment, the root of a project
MAY have a :file:`.venv` redirect file. This file acts as a pointer to where
-the (current) virtual environment to be used for the project is located
-(which, just like a :file:`.venv` directory, can be a logical or pysical path).
-This virtual environment may not be the only environment associated with the
-project, but it is considered the preferred virtual environment to use
-*at the moment* by other tools. The tool managing the virtual environment
-SHOULD update any :file:`.venv` redirect file as appropriate when the tool or
-the user desire a different virtual environment to be used by default by other
-tools.
+the (current) virtual environment to be used for the project is located. The
+file itself MUST NOT be a logical path; its containing directory and any
+parent directories MAY be logical paths. This virtual environment may not be
+the only environment associated with the project, but it is considered the
+preferred virtual environment to use *at the moment* by other tools. The tool
+managing the virtual environment SHOULD update any :file:`.venv` redirect file
+as appropriate when the tool or the user desires a different virtual
+environment to be used by default by other tools.
Tools looking for a virtual environment SHOULD look for either a :file:`.venv`
directory or a :file:`.venv` redirect file. IF a tool chooses to search parent
@@ -109,8 +109,10 @@ that only contains a newline is considered invalid.
The line in the :file:`.venv` redirect file MUST point to a directory
containing a virtual environment when being written. The path MAY use POSIX
path separators-- ``/`` --regardless of what the operating system's native path
-separator is. The path MAY be relative, and if so MUST be relative to the
-directory containing the :file:`.venv` file.
+separator is. The path MAY be relative; IF the path is relative THEN it MUST be
+resolved relative to the physical directory containing the redirect file. If
+that directory is reached through a logical path, it MUST be resolved to its
+physical path before resolving the relative path.
With regard to committing a :file:`.venv` redirect file to version control, it
MAY be done when the location of the virtual environment is considered static
@@ -205,6 +207,15 @@ name or ownership of the virtual environment, but e.g., virtual environments
have the prompt recorded in :file:`pyvenv.cfg`, so it does not need to be
listed separately from the environment where it may become stale.
+The discussion identified ambiguity about resolving relative paths in a
+:file:`.venv` redirect file when logical paths are involved. A logical path
+could refer to the redirect file itself or to any part of its containing
+directory. Two requirements address this. First, the redirect file itself MUST
+NOT be a symbolic link, avoiding ambiguity about whether relative paths are
+resolved against its logical or physical location. Second, the containing
+directory MUST be resolved to a physical path before any relative path in the
+redirect file is resolved.
+
While some projects may have multiple virtual environments available, the
concept of a current or default virtual environment is a constant. And saying
other tools shouldn't overwrite a :file:`.venv` redirect file they didn't
@@ -465,6 +476,11 @@ this PEP.
Change History
==============
+- XX-Oct-2026
+ - Require :file:`.venv` redirect files not be a symlink
+ - Require relative paths in a redirect file to be resolved relative to the
+ physical directory containing the file
+
- 24-Sep-2026
- Clarify :file:`.venv` redirect files can be logical or physical paths just
Nit: I’m not sure this phrase makes sense. I don’t think files can be paths,
logical or otherwise. Paths are human readable identifiers of files.
Would the term here “normal file” or “regular file” work here instead? Something like: “The file must be a normal file”.
The path MAY be relative; IF the path is relative THEN it MUST be
resolved relative to the physical directory containing the redirect file.
This addresses my feedback perfectly!
… although it feels a contradictory with this sentence from earlier in the PEP: “This PEP makes no judgment whether .venv is a physical or logical path to a directory containing a virtual environment, nor whether logical paths should be resolved to their physical equivalent before use.”. In fact, rereading that sentence I am a little confused what it would mean for .venv to be a physical or a logical path (per my earlier confusion about files not being paths).
If that directory is reached through a logical path, it MUST be resolved to its
physical path before resolving the relative path.
I don’t understand this sentence, and my attempts to understand are making me
worry that perhaps we’re not on the same page, haha. Perhaps you could help me
understand with an example?