You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Problem using virtualenvwrapper on Windows with git bash #124
I found two issues that I want to report. I am sorry that I do not have the time to submit a pull request.
In the doc, it mentions that to use on Windows with MSYS that the MSYS_HOME variable needs to be set.
In the Installation section under MSYS export MSYS_HOME=/c/msys/1.0
On my system that needs to be export MSYS_HOME=/c/msys64/usr
because there is no bin directory under msys64 so it needs /usr to be able to fins sh.exe in user_scripts.py _get_sys_shell()
This really just a doc problem, but I did have to go looking to find out why running postmkvirtualenv was failing in mkproject.
NOTE: I do think that MSYS_HOME as the variable name is not reflecting that it is needed for virtualenvwrapper.
There is a path issue when trying to connect the virtualenv to the project in mkproject. The issue is that python on windows, even running under bash uses Windows/non-posix style paths. This often leads to mixing of separators and the drive: prefix.
My fix was to remove the use of python to convert paths to absolute and expand vars, etc. Instead I switched to readlink. In the two functions: virtualenvwrapper_expandpath and virtualenvwrapper_absolutepath I just changed the the single line modifying the filepath variable.
In the Installation section under MSYS export MSYS_HOME=/c/msys/1.0
On my system that needs to be export MSYS_HOME=/c/msys64/usr
because there is no bin directory under msys64 so it needs /usr to be able to fins sh.exe in user_scripts.py _get_sys_shell()
Mmm, then you're using MSYS2, specifically... but so would anyone else using MSYS these days. Having commands for MSYS 1.0 in the docs is really pretty useless as it's been supplanted by MSYS2 for something like a decade now. MSYS2 doesn't use $MSYS_HOME, it uses the $MSYSTEM and $MSYSTEM_PREFIX variables to determine when a shell/process is running under an MSYS2 installation, and those are already set when Git Bash launches.
The virtualenvwrapper.sh script also already uses the $MSYSTEM variable to detect when it should go into Windows-paths mode — $MSYS_HOME is pretty much meaningless these days, and probably shouldn't be used in user_scripts.py either. In fact, NOT setting $MSYS_HOME is the right way to go, because a Git Bash session will have sh.exe in its default $PATH, which user_scripts.py will fall back to if it DOESN'T see an $MSYS_HOME shell variable set.
What it comes down to is, both the code and the docs (I assume you're referring to the Install > MSYS section of the docs) appear to be somewhat out of date, when it comes to Windows support. They should be updated for Git Bash and MSYS2, which is how anyone on Windows will be using virtualenvwrapper these days — not via MSYS 1.0.
My fix was to remove the use of python to convert paths to absolute and expand vars, etc. Instead I switched to readlink.
Yeah, there's an unfortunate problem with that approach... macOS doesn't have a readlink command. Believe me, there are about 100 software projects I've contributed to that could all be SO MUCH simpler if macOS just had a readlink command!
The problem with virtualenvwrapper.sh, when running against a Windows Python installation (like C:\Python314/python.exe) is that it tries to do a which python3 to find the appropriate Python executable, and Windows Python doesn't install a python3.exe executable/script.
If the wrapper script instead ran which python, it would get a path like /c/Python314/python (the unix-style equivalent of C:\Python314\Python.exe), and it would be able to use that executable to convert paths.
(Windows-style paths aren't actually a problem in Git Bash, as Python supports both path styles and the shell does automatic conversion where necessary. ls C:\\Users\\ will actually work just fine in Git Bash, and is the same as running ls C:/Users/ which is the same as running ls /c/Users/. The issue is the lack of a python3 command to run.)
It might be possible to have the virtualenvwrapper.sh script leverage its existing $MSYSTEM-based Windows environment detection, and have it switch the which python3 command to which python automatically, since that's more appropriate for that environment.
All of this is only relevant if you actually want to use a Windows Python installation for your virtual environment, like in that docs section I linked to above.
If you're fine with using a Unix-style Python as the virtual environment Python executable (like the one installed to C:\msys64\usr\bin\python3.exe), then the easiest approach is to use the "MSYS2 MSYS" launcher installed by MSYS2 to run Bash, instead of Git Bash. "MSYS2 MSYS" will drop you into a Bash shell that's largely disconnected from the Windows parts of the system, with its local $MSYSTEM_PREFIX/usr/bin/ directory already at the front of your $PATH. Then, the which python3 command run by virtualenvwrapper.sh will successfully locate /usr/bin/python3, avoiding all of the problems above.
(You have to make sure that pip install virtualenvwrapper is first run from that same shell environment, though. It won't work in the MSYS2 MSYS shell if it's installed to a Windows Python installation — which includes the ones you'd typically use in Git Bash.)
@carltongibson IMHO no. Since virtualenvwrapper doesn't supply a PowerShell activation script, being able to run the Bash script under Windows has value.
And anyway, if I'm right it should be easy to fix. The only thing it's doing wrong is running which python3 when attempting to discover a Python runtime in the $PATH. But with Python 2 now well past EOL, which python should find a Python 3 binary anywhere, so that could probably be changed to which python across-the-board.
And even if not, having it detect when it's running under Windows and using which python instead is trivial. The script is ALREADY detecting Windows, it's just that it currently happens right after the which python3.
There's a bigger problem with using py. We'd really want to give it an argument (like py -3 to run some version of Python 3), and it looks like it would take some restructuring to make $VIRTUALENVWRAPPER_PYTHON support a command with arguments. Right now it's a non-array variable that's typically called inside double-quotes. (Also, things like the which command would have to know to just run which py, even though the VIRTUALENVWRAPPER_PYTHON command would be py -3.)
I think if any version of Windows Python is installed, py can be relied on to be there... so if it's not, we probably don't have a usable Python either.
(In fact, it looks like py is not only compatible with Windows Store installs, but it supports auto-install of the requested version!)
$ py -2No suitable Python runtime foundPass --list (-0) to see all detected environments on your machineor set environment variable PYLAUNCHER_ALLOW_INSTALL to use wingetor open the Microsoft Store to the requested version.
...mind you, it doesn't appear to work very well:
$ py --list
-V:3.14* Python 3.14 (64-bit)
$ Set-Item Env:PYLAUNCHER_ALLOW_INSTALL 1
$ py -3.13
Launching winget to install Python. The following output is from the install process***********************************************************************
Found an existing package already installed. Trying to upgrade the installed package...
No available upgrade found.
No newer package versions are available from the configured sources.
***********************************************************************
Please check the install status and run your command again.
But, maybe that's because I'm still on Windows 10.
py appears to be doing something stupid, because winget install Python.Python.3.13 (which is what it should be running itself) worked just fine to install that runtime.
(Edit: Aha. If I try to run winget install -s msstore "Python 3.12" (which is how it's listed there, nothing like machine-readable identifiers 🙄), then it fails the same way because Python 3.14 is already installed. But winget install -s msstore --force "Python 3.12" works, and without removing Python 3.14. You'd think py would know it has to --force the installs, if it's going to bother providing that feature at all.)
UGGGGGGh. So it turns out, I was using an old version of the py command, from the "Python Launcher" package. Which is not the same as the new, improved py / pymanager from the Python Install Manager package, as now recommended by https://docs.python.org/dev/using/windows.html
When using the newpy:
The command to launch a specific Python version becomes something like py -V:3.14, or preferably even py exec -V3.14 - but the multiple-arguments issue is still there
py exec will automatically install missing runtimes by default, without needing an environment variable.1
A python3 command is actually installed, as a Windows "App execution alias", so which python3 would work to find a runtime
...However, that same Python documentation page recommends against using python3 as the Python command. It actually recommends using just python, assuming the runtime's dir is in the user's %PATH%, although py / py exec are available to run with specific versions or versions that might not be in the path.
So, at the very least, ignore everything I said about py and which python3 before this comment.
Notes
(And it actually works:)
$ py exec -V:3.12-m site
********************************************************************************
Installing Python 3.12.10.
Downloading: ..................................................................?
Extracting: ...................................................................?
To see all available commands, run 'py help'********************************************************************************
sys.path = [
'C:\\Users\\$ME','C:\\Users\\$ME\\AppData\\Local\\Python\\pythoncore-3.12-64\\python312.zip','C:\\Users\\$ME\\AppData\\Local\\Python\\pythoncore-3.12-64\\DLLs','C:\\Users\\$ME\\AppData\\Local\\Python\\pythoncore-3.12-64\\Lib','C:\\Users\\$ME\\AppData\\Local\\Python\\pythoncore-3.12-64','C:\\Users\\$ME\\AppData\\Roaming\\Python\\Python312\\site-packages','C:\\Users\\$ME\\AppData\\Local\\Python\\pythoncore-3.12-64\\Lib\\site-packages',
]
USER_BASE: 'C:\\Users\\$ME\\AppData\\Roaming\\Python' (exists)
USER_SITE: 'C:\\Users\\$ME\\AppData\\Roaming\\Python\\Python312\\site-packages' (exists)
ENABLE_USER_SITE: True
Activity
ferdnyc commentedon May 4, 2026
@julie777
Mmm, then you're using MSYS2, specifically... but so would anyone else using MSYS these days. Having commands for MSYS 1.0 in the docs is really pretty useless as it's been supplanted by MSYS2 for something like a decade now. MSYS2 doesn't use
$MSYS_HOME, it uses the$MSYSTEMand$MSYSTEM_PREFIXvariables to determine when a shell/process is running under an MSYS2 installation, and those are already set when Git Bash launches.The
virtualenvwrapper.shscript also already uses the$MSYSTEMvariable to detect when it should go into Windows-paths mode —$MSYS_HOMEis pretty much meaningless these days, and probably shouldn't be used inuser_scripts.pyeither. In fact, NOT setting$MSYS_HOMEis the right way to go, because a Git Bash session will havesh.exein its default$PATH, whichuser_scripts.pywill fall back to if it DOESN'T see an$MSYS_HOMEshell variable set.What it comes down to is, both the code and the docs (I assume you're referring to the Install > MSYS section of the docs) appear to be somewhat out of date, when it comes to Windows support. They should be updated for Git Bash and MSYS2, which is how anyone on Windows will be using virtualenvwrapper these days — not via MSYS 1.0.
Yeah, there's an unfortunate problem with that approach... macOS doesn't have a
readlinkcommand. Believe me, there are about 100 software projects I've contributed to that could all be SO MUCH simpler if macOS just had areadlinkcommand!The problem with
virtualenvwrapper.sh, when running against a Windows Python installation (likeC:\Python314/python.exe) is that it tries to do awhich python3to find the appropriate Python executable, and Windows Python doesn't install apython3.exeexecutable/script.If the wrapper script instead ran
which python, it would get a path like/c/Python314/python(the unix-style equivalent ofC:\Python314\Python.exe), and it would be able to use that executable to convert paths.(Windows-style paths aren't actually a problem in Git Bash, as Python supports both path styles and the shell does automatic conversion where necessary.
ls C:\\Users\\will actually work just fine in Git Bash, and is the same as runningls C:/Users/which is the same as runningls /c/Users/. The issue is the lack of apython3command to run.)It might be possible to have the
virtualenvwrapper.shscript leverage its existing$MSYSTEM-based Windows environment detection, and have it switch thewhich python3command towhich pythonautomatically, since that's more appropriate for that environment.Right now that detection is done here:
virtualenvwrapper/virtualenvwrapper.sh
Lines 76 to 83 in 2819e4d
...which is after the
$VIRTUALENVWRAPPER_PYTHONsetup. But there's nothing there that would prevent it from being moved before the Python checks.ferdnyc commentedon May 4, 2026
All of this is only relevant if you actually want to use a Windows Python installation for your virtual environment, like in that docs section I linked to above.
If you're fine with using a Unix-style Python as the virtual environment Python executable (like the one installed to
C:\msys64\usr\bin\python3.exe), then the easiest approach is to use the "MSYS2 MSYS" launcher installed by MSYS2 to run Bash, instead of Git Bash. "MSYS2 MSYS" will drop you into a Bash shell that's largely disconnected from the Windows parts of the system, with its local$MSYSTEM_PREFIX/usr/bin/directory already at the front of your$PATH. Then, thewhich python3command run byvirtualenvwrapper.shwill successfully locate/usr/bin/python3, avoiding all of the problems above.(You have to make sure that
pip install virtualenvwrapperis first run from that same shell environment, though. It won't work in the MSYS2 MSYS shell if it's installed to a Windows Python installation — which includes the ones you'd typically use in Git Bash.)carltongibson commentedon May 4, 2026
@ferdnyc Do you think this issue is out of scope really, and can be closed? (The docs do very much punt of Windows support.)
ferdnyc commentedon May 6, 2026
@carltongibson IMHO no. Since virtualenvwrapper doesn't supply a PowerShell activation script, being able to run the Bash script under Windows has value.
And anyway, if I'm right it should be easy to fix. The only thing it's doing wrong is running
which python3when attempting to discover a Python runtime in the$PATH. But with Python 2 now well past EOL,which pythonshould find a Python 3 binary anywhere, so that could probably be changed towhich pythonacross-the-board.And even if not, having it detect when it's running under Windows and using
which pythoninstead is trivial. The script is ALREADY detecting Windows, it's just that it currently happens right after thewhich python3.carltongibson commentedon May 6, 2026
I think the correct approach on windows then is to use the
pylauncher tool to find installed Pythons.(Although as I write that I'm not certain it's always available, if installing from the Windows App Store)
ferdnyc commentedon May 6, 2026
There's a bigger problem with using
py. We'd really want to give it an argument (likepy -3to run some version of Python 3), and it looks like it would take some restructuring to make$VIRTUALENVWRAPPER_PYTHONsupport a command with arguments. Right now it's a non-array variable that's typically called inside double-quotes. (Also, things like thewhichcommand would have to know to just runwhich py, even though theVIRTUALENVWRAPPER_PYTHONcommand would bepy -3.)I think if any version of Windows Python is installed,
pycan be relied on to be there... so if it's not, we probably don't have a usable Python either.ferdnyc commentedon May 6, 2026
(In fact, it looks like
pyis not only compatible with Windows Store installs, but it supports auto-install of the requested version!)...mind you, it doesn't appear to work very well:
But, maybe that's because I'm still on Windows 10.
ferdnyc commentedon May 6, 2026
pyappears to be doing something stupid, becausewinget install Python.Python.3.13(which is what it should be running itself) worked just fine to install that runtime.(Edit: Aha. If I try to run
winget install -s msstore "Python 3.12"(which is how it's listed there, nothing like machine-readable identifiers 🙄), then it fails the same way because Python 3.14 is already installed. Butwinget install -s msstore --force "Python 3.12"works, and without removing Python 3.14. You'd thinkpywould know it has to--forcethe installs, if it's going to bother providing that feature at all.)ferdnyc commentedon May 6, 2026
UGGGGGGh. So it turns out, I was using an old version of the
pycommand, from the "Python Launcher" package. Which is not the same as the new, improvedpy/pymanagerfrom the Python Install Manager package, as now recommended by https://docs.python.org/dev/using/windows.htmlWhen using the new
py:py -V:3.14, or preferably evenpy exec -V3.14- but the multiple-arguments issue is still therepy execwill automatically install missing runtimes by default, without needing an environment variable.1python3command is actually installed, as a Windows "App execution alias", sowhich python3would work to find a runtime...However, that same Python documentation page recommends against using
python3as the Python command. It actually recommends using justpython, assuming the runtime's dir is in the user's%PATH%, althoughpy/py execare available to run with specific versions or versions that might not be in the path.So, at the very least, ignore everything I said about
pyandwhich python3before this comment.Notes