Update: I just installed the latest Git for Windows seconds ago, and they now have a box to check to fix the winpty
Python issue in Git Bash! See here:
I still recommend also doing the steps below, however:
Original, and probably more-reliable, answer:
Python doesn't work in Git Bash (it just hangs or freezes forever); and getting Linux hash-bangs to work in Windows
Note that when Git Bash freezes when I try to run Python, I can't kill it with Ctrl + C nor Ctrl + D. I have to close the Git Bash terminal to kill it. :(
For those of us coming to Windows from Linux, you're probably also used to calling python3
at the command line, and using a hash bang at the top of your Python files that looks like this:
#!/usr/bin/env python3
...so that you can just make the file executable with chmod +x my_script.py
and then run it directly as ./my_script.py
, instead of having to use python3 my_script.py
.
So, let's fix all of the problems mentioned above.
Quick summary:
Add these two aliases and this PATH fix to the bottom of your ~/.bashrc
file so that you can run python
or python3
interactively in Git Bash:
alias python='winpty python'
alias python3='winpty python'
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
Add this ~/bin/python3
executable wrapper so that you can use your #!/usr/bin/env python3
hash bang in Python scripts:
#!/usr/bin/env bash
winpty python "$@"
Close and re-open all Git Bash terminals, or call . ~/.bashrc
inside each of them. Then:
# ensure your aliases exist
alias python # expected output: `alias python='winpty python'`
alias python3 # expected output: `alias python3='winpty python'`
# ensure your `python3` executable exists
which python3 # expected output: `/c/Users/myusername/bin/python3`
Test:
# Both of these open Python 3 interactively
# - then type `exit()` to exit
python
python3
For this hello_world.py
script:
#!/usr/bin/env python3
print("Hello world.")
The following all run it:
# all 3 of these run `hello_world.py` in Python 3
# 1. Windows style
python hello_world.py
# 2. Linux style
python3 hello_world.py
# 3. Hash-bang Linux style
./hello_world.py
If that all made sense to you, and you did it all, you're done. Otherwise, read on for more details and information, including troubleshooting.
Details
Step 1: make python
and python3
available interactively in the Git Bash terminal
First, to get both python
and python3
to work interactively in your Git Bash terminal and not hang or freeze forever, run these commands:
# Add interactive `python` and `python3` aliases.
# - NB: it is *not* a mistake that both aliases point to `python`. That is how
# it is supposed to be!
echo -e "\n" >> ~/.bashrc
echo "alias python='winpty python'" >> ~/.bashrc
echo "alias python3='winpty python'" >> ~/.bashrc
This is the equivalent of creating a ~/.bashrc
file and adding these aliases to the bottom of it:
alias python='winpty python'
alias python3='winpty python'
Now close and re-open your Git Bash terminals to bring in these changes.
You can now run python
or python3
interactively in the Git Bash terminal. Yaaay! For why this is necessary to call python
through winpty
, see @VonC's answer here:
Winpty is a compatibility layer that allows you to run a Windows console application from a Linux terminal.
- When you cross-compile a program for Windows from Linux, the resulting binary will be a Windows console application that can be run directly from a Linux terminal without the need for
winpty
.
- However, if you build a program natively on Windows, the resulting binary will be a Windows GUI application that cannot be run from a Linux terminal.
In order to run a Windows GUI application from a Linux terminal, you need to use winpty
.
Step 2: make the #!/usr/bin/env python3
hash-bang work too
For this to work, we need to add a custom ~/bin/python3
executable Bash wrapper to our PATH.
Open your ~/.bashrc
file and add this to the bottom of it to automatically add ~/bin
to our path if that directory exists:
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
Create the ~/bin
dir:
mkdir -p ~/bin
Re-source your ~/.bashrc
file, or close and re-open all Git Bash terminals. If you don't know what "source"ing means, read my answer here: What is the difference between source and export?.
. ~/.bashrc
Now create a file at path ~/bin/python3
, and paste this into it. Save and close the file when done.
#!/usr/bin/env bash
winpty python "$@"
Ensure it is executable:
chmod +x ~/bin/python3
Now, create a test file. Create a file called hello_world.py
, and paste the following into it:
#!/usr/bin/env python3
print("Hello world.")
Make the file executable, and run it directly:
# make it executable
chmod +x hello_world.py
# run it
./hello_world.py
You'll see:
Hello world.
Done! You now have 3 ways to run this script!:
# 1. Windows style
python hello_world.py
# 2. Linux style
python3 hello_world.py
# 3. Hash-bang Linux style
./hello_world.py
How does this all work?
Exactly how this all works is a little bit tricky.
First off, when you manually run python
or python3
all alone to get an interactive session, or python hello_world.py
or python3 hello_world.py
to run a file, it accesses your Bash aliases defined in your ~/.bashrc
file, and runs winpty python
instead. This is required for the calls to work properly in Git Bash, for the reasons already explained in @VonC's answer here.
Bash aliases are only available when a user, such as yourself, directly runs an alias in the Git Bash terminal. They are not available to the system nor to any other process started by the system. So, when you run ./hello_world.py
, the #!/usr/bin/env python3
hash-bang does not find and run your python3
alias. Rather, it finds and runs your ~/bin/python3
executable Bash wrapper instead, which also performs the Python call through winpty
, as required.
Troubleshooting: various errors you may see if you don't do the above right
Problem: Running python
or python3
hangs forever in the Git Bash terminal
Solution: You forgot to add the two aliases which call winpty python
. Add them.
Problem: Running python3
opens up the Microsoft Store and tries to install Python.
Solution: You forgot to make the alias python3='winpty python'
alias.
Problem: Hash-bangs don't work. Running ./hello_world.py
says:
Python was not found; run without arguments to install from the Microsoft Store, or disable this shortcut from Settings > Manage App Execution Aliases.
Solution: you forgot to create the ~/bin/python
wrapper executable. If you have created it, ensure it is executable. If both of those things are done, ensure ~/bin
is in your PATH. See above to add a code chunk to ~/.bashrc
to do that.
Problem: Hash-bangs don't work. Running ./hello_worl.py
says:
/usr/bin/env: ‘python3’: No such file or directory
You have turned off your python.exe
and python3.exe
Windows "App execution aliases", as explained here, but you have not created the ~/bin/python
wrapper executable.
Solution: you forgot to create the ~/bin/python
wrapper executable. If you have created it, ensure it is executable. If both of those things are done, ensure ~/bin
is in your PATH. See above to add a code chunk to ~/.bashrc
to do that.
Problem: you get this:
`winpty: error: cannot start '"C:/Program Files/WindowsApps/Microsoft.DesktopAppInstaller_1.20.1881.0_x64__8wekyb3d8bbwe/AppInstallerPythonRedirector.exe"': Access is denied. (error 0x5)
Solution:
Honestly I can't remember how I got this error now, but it was one of my many errors I stumbled upon until I figured out my solutions explained in my answer above.
Other references
- I learned about the
alias python='winpty python.exe'
alias in @Vitaliy Terziev's answer here.
winpty
is also recommended by MSYS2 (the makers of the underlying system that Git Bash uses) at the bottom of this page here: https://www.msys2.org/wiki/Terminals/
See also
- My answer: Change the location of the
~
directory in a Windows install of Git Bash
python -i
solves it. – Ecclesiasteswinpty
? – Bespread