I cannot link Python 3.8 over system Python 3.9.
I have few installed python versions (3.8, 3.10, etc) by brew and system Python 3.9.
P.S. I cannot uninstall system one (it does not appear in Applications).
$ python3 --version
Python 3.10.9
$ brew unlink python@$(python3 --version | grep -oE '[0-9] \.[0-9] '); brew link [email protected]
Unlinking /opt/homebrew/Cellar/[email protected]/3.10.9... 25 symlinks removed.
Warning: Already linked: /opt/homebrew/Cellar/[email protected]/3.8.16
To relink, run:
brew unlink [email protected] && brew link [email protected]
$ python3 --version
Python 3.9.6
$ type python3
python3 is /usr/bin/python3
$ python3[press TAB]
python3 python3-config python3.10 python3.10-config python3.11 python3.11-config
$ python3.8 --version
zsh: command not found: python3.8
$ echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
Questions:
- How to set brewed Python over system one?
How to uninstall system python?(not recommended)- How to link
python
in addition topython3
? Why there is no(solved withpython3.8
available?brew reinstall [email protected]
)
UPD:
python3.8
became available afterbrew reinstall [email protected]
.
CodePudding user response:
- How to set brewed Python over system one?
All you need to do is prepend /opt/homebrew/bin
to the beginning of your path. Your $PATH
variable seems to be correctly set, so if it is not working I'd try restarting your terminal.
If all else fails, you can also explicitly prepend /opt/homebrew/opt/python@VERION_NUMBER/bin
to the beginning of your path.
- How to link python in addition to python3?
If you run brew info python
, Homebrew tells you this caveat:
Unversioned symlinks
python
,python-config
,pip
etc. pointing topython3
,python3-config
,pip3
etc., respectively, have been installed into /opt/brew/opt/[email protected]/libexec/bin
So, all you need to do is prepend /opt/brew/opt/python@VERSION_NUMBER/libexec/bin
to the beginning of your path. Just add this line to the end of your zshrc, bashrc, or equivalent:
export PATH="/opt/brew/opt/python@VERSION_NUMBER/libexec/bin:$PATH"
This will make all the unversioned Python utils available to you.
CodePudding user response:
- It is best to avoid directly overriding (modifying) symbolic or hard links pointing to the system's python version. These might be used by system functions/scripts which are (hopefully) tested against that specific python binary. Changing the version (especially downgrading, but sometimes even upgrading) can break things for the OS.
- For the same reason stated above, uninstalling/deleting the system's python should also be avoided.
- I struggled myself with MacOS not having
python
as an executable, so I'll focus my answer on that. - Looks like you already found a way to resolve that.
I can think of 4 ways to get a python
executable;
Method #1 - probably not what you want
The easy way to make python
available in (z)shell on mac is to add an alias:
echo "alias python=python3" >> ~/.zshrc
With this, in all new zsh sessions (or where .zshrc
is reloaded), running python
will run the python3
executable in your PATH. You can also set the alias's target to be a full path, so point it to the python version you like (if, for example, one is installed using homebrew). There are two problems: changing the target requires reloading .zshrc
, and this will only take effect when executing python from an open shell (will not work for executable scripts/entrypoints - more on that later).
Method #2 - optimal for homebrew
Unversioned python
, pip
and other such symlinks are installed in libexec/bin
directories of brew packages. If you are using homebrew you can add these to your path, like so:
echo 'export PATH="$PATH:/opt/homebrew/opt/python@3/libexec/bin"' >> .zprofile
As homebrew uses symlinks for package versioning, you can replace python@3
in the above example with a more explicit version (e.g. [email protected]
or [email protected]
).
Method #3 - requires admin privileges
If you have admin privileges, you can add a symlink in your path to the executable, like so (change /usr/bin/python3
to the brew's python executable you like):
sudo ln -s /usr/bin/python3 /usr/local/bin/python
While hardlinks will work as well, I recommend avoiding them as there might be a chance that it will negatively affect minor version upgrades by keeping the older executable (haven't tested myself).
The upside of this method is that it will probably work for all users and all applications, as it is extremely rare for applications to not include /usr/local/bin
in the execution search path.
Method #4 - intermediary executable
This (much like method #2) probably won't work for applications that are not invoked by (z)shell (possibly your favorite IDE), but it is most flexible, and does not require admin privileges. It entails adding an intermediary binary, and adding that to your PATH. I usually create a bin
directory in my homedir for such occasions, so I'll use that path in the examples. First, create the executable:
mkdir ~/bin
echo '#!/bin/sh\nexec /usr/bin/python3 "$@"' > ~/bin/python
chmod x ~/bin/python
Now add ~/bin
to your shell's path:
echo 'export PATH="$PATH:$HOME/bin"' >> .zprofile
Alternatively, .zshrc
or .zshenv
can be used, but additional precaution has to be taken to avoid repeatedly adding ~/bin
to the path in subshells:
echo '_home_bindir="$HOME/bin"\n[ "${PATH##*:}" = "$_home_bindir" ] || export PATH="$PATH:$_home_bindir"' >> ~/.zshrc
Now, every new shell (or if using .zshrc
- if it is reloaded) will have python
executable in its path, and you can easily edit the file to point to your favorite python version.
Notes:
Method #2 is probably the best option if using homebrew, which is the case in question. Still, as I struggled with not having a python
executable on a "clean" MacOS installation (without homebrew), I've added methods #1, #3, and #4, in case I'm not the only one not using homebrew's python.
Methods #2, #3, and #4, allow for executable scripts/entrypoints. By that, I'm referring to executable scripts with shebang, most commonly using the env
executable:
#!/usr/bin/env python
These 3 methods will also honor additional python arguments (e.g. python -u
).
As MacOS no longer comes with a python
executable (only python3
), I think that method #3 is fairly safe to use (at least from a perspective of not breaking OS scripts). As for $PATH
manipulation, I wouldn't recommend prepending it with user-writeable paths (like ~/bin
), as this may lead to a security issue, or worse - a debugging nightmare (of course, no one would ever create executables like ~/bin/ls
or ~/bin/which
, right?).
As for the specific shell, this will also work for bash by changing the relevant files (.z..
to .bash..
) as long as the profile/rc files are properly loaded. For other shells (e.g. tcsh
) the syntax needs to be adjusted.