Scenario
I have a script in a venv (EnvA) that:
- creates a new uv venv (EnvB)
- installs some packages to the new venv (EnvB)
- runs a script in that venv(EnvB)
- tries to delete EnvB via the EnvA script.
However the venv deletion fails on Windows since there are overlapping dependencies between the two environments (both depend on e.g. markupsafe which contains pyd files that are automatically loaded by python)
This is because UV uses hardlinks to the uv cache, so deleting that file fails since it is hardlinked to the file in uv cache and that file (.pyd) is automatically loaded by python.
Switching to using symlinks solves the issue, but i don't have control over how users will run this script. What is the decision behind using hardlinks by default on windows? I have little control over how the application runs uv (done by 3rd party library) so this is causing issues for my users. I guess i could patch the environment variable UV_LINK_MODE env var before invoking the 3rd party lib, but that feels like a hack and i'm not sure if it will work well.
Minimally reproducible example
- Create a new venv:
uv venv .venv
- Install
markupsafe into that venv: uv pip install markupsafe
- Create a
main.py with contents like so:
import subprocess
import shutil
import os
os.mkdir("testdir")
subprocess.run(["uv", "venv", ".venv"], cwd="./testdir")
subprocess.run(["uv", "pip", "install", "markupsafe"], cwd="./testdir")
shutil.rmtree("testdir")
- Run
main.py via python main.py
- Notice that it will fail on Windows:
PermissionError: [WinError 5] Access is denied: 'testdir\\.venv\\Lib\\site-packages\\markupsafe\\_speedups.cp310-win_amd64.pyd'
- Try changing link mode (e.g. via environment variable) to symlink and see that it then works when running
python main.py
I think it boils down to python automatically loading .pyd files in your venv and then uv hardlinking to the cache, and when the file is loaded/has open file descriptors windows will not allow us to delete the hardlink. This is not only an issue for only markupsafe, but all libraries that use .pyd files, this was just an example.
tl;dr
if you have a python script, with any dependency containing a .pyd file, and this script tries to delete a .venv containing a hardlink to the same .pyd file then Windows will throw you an "Access is denied" error.
Version
uv: 0.4.17
Scenario
I have a script in a venv (EnvA) that:
However the venv deletion fails on Windows since there are overlapping dependencies between the two environments (both depend on e.g.
markupsafewhich containspydfiles that are automatically loaded by python)This is because UV uses hardlinks to the uv cache, so deleting that file fails since it is hardlinked to the file in uv cache and that file (.pyd) is automatically loaded by python.
Switching to using symlinks solves the issue, but i don't have control over how users will run this script. What is the decision behind using hardlinks by default on windows? I have little control over how the application runs
uv(done by 3rd party library) so this is causing issues for my users. I guess i could patch the environment variableUV_LINK_MODEenv var before invoking the 3rd party lib, but that feels like a hack and i'm not sure if it will work well.Minimally reproducible example
uv venv .venvmarkupsafeinto that venv:uv pip install markupsafemain.pywith contents like so:main.pyviapython main.pyPermissionError: [WinError 5] Access is denied: 'testdir\\.venv\\Lib\\site-packages\\markupsafe\\_speedups.cp310-win_amd64.pyd'python main.pyI think it boils down to python automatically loading
.pydfiles in your venv and then uv hardlinking to the cache, and when the file is loaded/has open file descriptors windows will not allow us to delete the hardlink. This is not only an issue for only markupsafe, but all libraries that use.pydfiles, this was just an example.tl;dr
if you have a python script, with any dependency containing a
.pydfile, and this script tries to delete a.venvcontaining a hardlink to the same.pydfile then Windows will throw you an "Access is denied" error.Version
uv:
0.4.17