Why Python's Path.home() Returns the Wrong Directory in MSYS2 MinGW64 Bash
How to Fix Python's Path.home() in MSYS2 MinGW Bash
Running Python in MinGW64 bash and getting `C:/Users/Bob` from `Path.home()`? Here's why MSYS2_ARG_CONV_EXCL won't help and the one-line fix that gives Python the right home directory.
Looking through my bashrc again today and wanted to make sure my paths were still good because Python decided to seemingly randomly use the Windows path convention starting with C:
haiyaaa π€¦
Anyway, I checked and yes it's there in the bashrc:
export MSYS2_ARG_CONV_EXCL="*"Sound familiar? If you're running Python in MinGW64 bash on Windows, Path.home() is probably lying to you too - and MSYS2_ARG_CONV_EXCL won't save you.
What You'll Learn About Python Paths in MSYS2 π
This is a practical guide to why Path.home() returns the wrong directory in MinGW64 and exactly how to fix it.
You'll understand:
- MSYS2 Path Conversion: What MSYS2_ARG_CONV_EXCL does and why it doesn't help here
- Why Path.home() Ignores MSYS2: How Python calls the Windows API directly, bypassing bash environment variables
- Reproducing the Problem: How to see the wrong path for yourself in the Python REPL
- The One-Line Fix: Using os.environ.get('HOME') to get the correct MinGW64 home directory
By the end, Python will use your MinGW64 home directory instead of the Windows one.
Ready to fix it? π
What does MSYS2_ARG_CONV_EXCL="*" do?
The * wildcard tells MSYS2:
"Do not convert any arguments when passing them to native Windows programs."
So when you call a native Windows executable from bash:
python3 --path=/foo/barWith MSYS2_ARG_CONV_EXCL="*", the argument stays as /foo/bar instead of being converted to C:/msys64/foo/bar.
This prevents MSYS2's automatic path conversion from breaking:
- Docker commands
- Python scripts expecting literal paths
- Node tools
- Git commands
- Build systems
But here's the catch: This only affects arguments and environment variables passed TO programs. It doesn't affect what happens INSIDE those programs.
In my case:
/c/Users/Bob stays /c/Users/Bob
/mnt/data stays /mnt/data
--path=/foo/bar stays --path=/foo/bar
Nothing is rewritten into C:\Users\Bob or worse still C:/Users/Bob
But Python didn't listen. In fact Python wanted a Path.home(); and who can blame them.
Python got WindowsPath(C:/Users/Bob) I mean what? Not even C:\Users\Bob but C:/ - this is most certainly the beginnings of a mangled path and the last thing we need are mangled paths.
Why Path.home() Ignores MSYS2_ARG_CONV_EXCL
When you run this in Python from MinGW64 bash:
from pathlib import Path
print(Path.home())You get:
WindowsPath('C:/Users/Bob')Even in MinGW64 bash where my home is /c/msys64/home/Bob, not C:/Users/Bob!
Why does this happen?
Because Path.home() doesn't read command-line arguments or environment variables that MSYS2 can intercept. Instead, it directly calls the Windows API to ask "What is this user's home directory?" And Windows always answers with the Windows home directory: C:/Users/Bob.
From the official MSYS2 docs:
When calling native executables from the context of Cygwin, then all the arguments that look like Unix paths will get auto converted to Windows.
The key phrase is "arguments that look like Unix paths". Python's internal API calls bypass this conversion entirely.
By setting export MSYS2_ARG_CONV_EXCL="*" we can make MSYS2 behave more like a Unix shell.
But not for when Python wants to go Path.home() apparently.
So let's fix this so Python can use the $HOME environment variable that MINGW64 sets.
So Python wants to go Home in Bash and MSYS2 on Windows?
If you didn't already know, you can print your home directory in Python π
from pathlib import Path
print(Path.home())Or, if you're already in the Python REPL with a single, clean line:
Path.home()Want to test it quickly in the REPL? Import Path first, or you'll hit this:
>>> print(Path.home())
Traceback (most recent call last):
File "<python-input-0>", line 1, in <module>
print(Path.home())
^^^^
NameError: name 'Path' is not definedNow import Path from pathlib, then run Path.home() again.
>>> from pathlib import Path
>>> Path.home()
WindowsPath('C:/Users/Bob')What? π You still get the Windows User path while sitting in MinGW64 bash.
That mismatch is exactly the trap, and exactly what we're fixing next.
The Solution: Use $HOME Environment Variable
MINGW64 bash sets the $HOME environment variable to your MinGW64 home directory:
echo $HOME
# Output: /c/msys64/home/BobNote: Bash displays
$HOMEas a Unix-style path, but Python reads the underlying Windows environment variable directly soos.environ.get('HOME')returnsC:\msys64\home\Bob.
So instead of using Path.home(), use:
import os
from pathlib import Path
# Prefer $HOME if set, fallback to Path.home()
home = os.environ.get('HOME', str(Path.home()))Now when Python runs in MINGW64 bash:
>>> import os
>>> print(os.environ.get('HOME'))
C:\msys64\home\BobThat's the MinGW64 home directory, not the Windows user home.
Quick Recap for Python Users
The Problem Before the Fix:
Path.home()βC:/Users/Bob(Windows home)- Expected β
C:\msys64\home\Bob(MINGW64 home)
Why MSYS2_ARG_CONV_EXCL doesn't help:
- It only affects arguments passed between programs
Path.home()calls Windows API directly, no arguments involved
The Fix: Using os.environ['HOME'] β C:\msys64\home\Bob (the MinGW64 MSYS2 bash home)
import os
from pathlib import Path
home = os.environ.get('HOME', str(Path.home()))Why this works:
- MINGW64 bash sets
$HOMEto your MinGW64 home directory - Python reads it via
os.environ['HOME'] - Falls back to Windows home if
$HOMEisn't set
So you can do Python in Bash on almost POSIX without WSL, and Python will use the correct home directory for your MinGW64 environment.
Now Python knows where home is, you can implement your wizardry and cast the right spells!
Go build things that work.
k bbb π
Login to vote on this article