I had a problem where python was not finding modules installed by pip while in the virtualenv.
I have narrowed it down, and found that when I call python when my virtualenv in activated, it still reaches out to /usr/bin/python instead of /home/liam/dev/.virtualenvs/noots/bin/python.
When I use which python in the virtualenv I get:
/home/liam/dev/.virtualenvs/noots/bin/python
When I look up my $PATH variable in the virtualenv I get:
bash: /home/liam/dev/.virtualenvs/noots/bin:/home/liam/bin:/home/liam/.local/bin:/home/liam/bin:/home/liam/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin: No such file or directory
and yet when I actually run python it goes to /usr/bin/python
To make things more confusing to me, if I run python3.5 it grabs python3.5 from the correct directory (i.e. /home/liam/dev/.virtualenvs/noots/bin/python3.5)
I have not touched /home/liam/dev/.virtualenvs/noots/bin/ in anyway. python and python3.5 are still both linked to python3 in that directory. Traversing to /home/liam/dev/.virtualenvs/noots/bin/ and running ./python, ./python3 or ./python3.5 all work normally.
I am using virtualenvwrapper if that makes a difference, however the problem seemed to occur recently, long after install virtualenv and virtualenvwrapper
My problem was that i recently moved my project with virtualenv to another location, due to this activate script had wrong VIRTUAL_ENV path.
$ cat path_to_your_env/bin/activate
... # some declarations
VIRTUAL_ENV="/path_to_your_env/bin/python" # <-- THIS LINE
export VIRTUAL_ENV
... # some declarations
To fix this, just update VIRTUAL_ENV in activate script.
Also you maybe need to fix first line of your bin/pip to link to real python path.
As tdelaney suggested in the comments, I ran alias and found that I had previously aliased python to /usr/bin/python3.5 in my .bashrc.
I removed that alias from my .bashrc, ran unalias python, and source ~/.bashrc and the problem was solved.
If you don't get the program that which says you should get, you need to look higher up the chain than the platform executor. Shells typically have a way to alias commands and on most unixy shells you can just enter alias to see which commands have been remapped. Then its just a matter of going to the config files for your shell and removing the alias.
Sometimes people alias python to try to sort out which python they should be using. But there are usually other, better ways. On my linux machine, for example, python3 is in the path but is a symlink to the real python I am using.
td#mintyfresh ~ $ which python3
/usr/bin/python3
td#mintyfresh ~ $ ls -l /usr/bin/python3
lrwxrwxrwx 1 root root 9 Feb 17 2016 /usr/bin/python3 -> python3.4
td#mintyfresh ~ $
This is nice because non-shell programs running python get the same one I do and virtual environments work naturally.
On Cygwin, I still have a problem even after I created symlink to point /usr/bin/python to F:\Python27\python.exe. Here, after source env/Scripts/activate, which python is still /usr/bin/python.
After a long time, I figured out a solution. Instead of using virtualenv env, you have to use virtualenv -p F:\Python27\python.exe env even though you have created a symlink.
I'm currently having the same problem. Virtualenv was created in Windows, now I'm trying to run it from WSL.
In virtualenv I renamed python.exe to python3.exe(as I have only python3 command in WSL). In $PATH my virtualenv folder is first, there is no alias for python. I receive which python3
/usr/bin/python3. In /usr/bin/python3 there is symlink `python3 -> python3.6. I suppose it doesn't matter for order resolution.
Had the exact same problem.
I ran:
virtualenv -p /venv/bin/python3 env
and got a permission denied.
so i tried:
sudo chmod 777 -R /venv/bin
which python and print(sys.executable)
were not agreeing for me. This meant that with an active virtualenv pip install <package> would install to the virtualenv, but running python would be the base install.
I eventually got around this by running
virtualenv -p \path\to\python.exe --always-copy <venvName>
I'm not sure if specifying the path to the original python is really necessary, but can't hurt. According to the man page:
--copies, --always-copy try to use copies rather than symlinks, even when symlinks are the default for the platform (default: False)
I'm using windows powershell with msys64.
Related
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 python#3.8
Unlinking /opt/homebrew/Cellar/python#3.10/3.10.9... 25 symlinks removed.
Warning: Already linked: /opt/homebrew/Cellar/python#3.8/3.8.16
To relink, run:
brew unlink python#3.8 && brew link python#3.8
$ 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 to python3?
Why there is no python3.8 available? (solved with brew reinstall python#3.8)
UPD:
python3.8 became available after brew reinstall python#3.8.
UPD 2:
It looks like there is no way to fix this properly. Must be a bug of 3.8 installer.
Here is workaround commands:
mkdir ~/bin/
ln -s /opt/homebrew/bin/python3.8 ~/bin/python
chmod u+x,og-rwx ~/bin/python
And this ~/bin to your PATH.
#micromoses described the same in Method #4.
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 to
python3, python3-config, pip3 etc., respectively, have been installed into
/opt/brew/opt/python#3.10/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.
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. python#3.8 or python#3.10).
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.
This question already has answers here:
How to change default Python version?
(19 answers)
Closed 1 year ago.
I'm running Mountain Lion and the basic default Python version is 2.7. I downloaded Python 3.3 and want to set it as default.
Currently:
$ python
version 2.7.5
$ python3.3
version 3.3
How do I set it so that every time I run $ python it opens 3.3?
Changing the default python executable's version system-wide could break some applications that depend on python2.
However, you can alias the commands in most shells, Since the default shells in macOS (bash in 10.14 and below; zsh in 10.15) share a similar syntax. You could put
alias python='python3'
in your ~/.profile, and then source ~/.profile in your ~/.bash_profile and/or your~/.zsh_profile with a line like:
[ -e ~/.profile ] && . ~/.profile
This way, your alias will work across shells.
With this, python command now invokes python3. If you want to invoke the "original" python (that refers to python2) on occasion, you can use command python, which will leaving the alias untouched, and works in all shells.
If you launch interpreters more often (I do), you can always create more aliases to add as well, i.e.:
alias 2='python2'
alias 3='python3'
Tip: For scripts, instead of using a shebang like:
#!/usr/bin/env python
use:
#!/usr/bin/env python3
This way, the system will use python3 for running python executables.
You can solve it by symbolic link.
unlink /usr/local/bin/python
ln -s /usr/local/bin/python3.3 /usr/local/bin/python
Open ~/.bash_profile file.
vi ~/.bash_profile
Then put the alias as follows:
alias python='python3'
Now save the file and then run the ~/.bash_profile file.
source ~/.bash_profile
Congratulation !!! Now, you can use python3 by typing python.
python --version
Python 3.7.3
I encountered this issue as well, so I thought I should post an updated answer. Please note that this will only apply to a Mac-based setup (I haven't tried it with Windows or any flavor of Linux). The simplest way to get this working is to install Python via Brew. If you don't have brew installed, you will need to do that first. Once installed, do the following in at the terminal:
brew install python
This will install Python 3. After it's installed, run this:
ls -l /usr/local/bin/python*
You will see all of the links created by brew to its Python install. It will look something like this:
lrwxr-xr-x 1 username admin 36 Oct 1 13:35 /usr/local/bin/python3# -> ../Cellar/python/3.7.4_1/bin/python3
lrwxr-xr-x 1 username admin 43 Oct 1 13:35 /usr/local/bin/python3-config# -> ../Cellar/python/3.7.4_1/bin/python3-config
lrwxr-xr-x 1 username admin 38 Oct 1 13:35 /usr/local/bin/python3.7# -> ../Cellar/python/3.7.4_1/bin/python3.7
lrwxr-xr-x 1 username admin 45 Oct 1 13:35 /usr/local/bin/python3.7-config# -> ../Cellar/python/3.7.4_1/bin/python3.7-config
lrwxr-xr-x 1 username admin 39 Oct 1 13:35 /usr/local/bin/python3.7m# -> ../Cellar/python/3.7.4_1/bin/python3.7m
lrwxr-xr-x 1 username admin 46 Oct 1 13:35 /usr/local/bin/python3.7m-config# -> ../Cellar/python/3.7.4_1/bin/python3.7m-config
The first row in this example shows the python3 symlink. To set it as the default python symlink run the following:
ln -s -f /usr/local/bin/python3 /usr/local/bin/python
You will have to reload your current terminal shell to use the new symlink in that shell. Run this command to reload your shell:
exec $SHELL -l
You're all set now. Now, you can do:
which python
and it should show:
/usr/local/bin/python
All newly opened shell sessions will (should) automatically use the new symlink. To test this, open a new terminal shell and run the following:
python --version
Go to terminal type:
alias python=python3.x
This will setup default python as python3.x
This worked for me. I added alias and restarted my terminal:
alias python=/usr/local/bin/python3
The following worked for me
cd /usr/local/bin
mv python python.old
ln -s python3 python
Go to 'Applications', enter 'Python' folder, there should be a bash script called 'Update Shell Profile.command' or similar. Run that script and it should do it.
Update: It looks like you should not update it: how to change default python version?
I believe most of people landed here are using ZSH thorugh iterm or whatever, and that brings you to this answer.
You have to add/modify your commands in ~/.zshrc instead.
$ sudo ln -s -f $(which python3) $(which python)
done.
Mac users just need to run the following code on terminal
brew switch python 3.X.X
3.x.x should be the new python version.
This will update all the system links.
UPDATE
For Newer version of MAC use
brew link python 3.X.X
Suggestions to alias python to python3 will cause problems with virtual environments that set the version of python (eg: pyenv). With pyenv, you can set the version globally like so:
pyenv global 3.8.2
and then in any specific project, you can create a .python-version file which has the python version inside of it:
pyenv local 2.7.1
This is the best way to manage multiple versions of python on a system in my opinion.
I think when you install python it puts export path statements into your ~/.bash_profile file. So if you do not intend to use Python 2 anymore you can just remove that statement from there. Alias as stated above is also a great way to do it.
Here is how to remove the reference from ~/.bash_profile
- vim ./.bash_profile
- remove the reference (AKA something like: export PATH="/Users/bla/anaconda:$PATH")
- save and exit
- source ./.bash_profile to save the changes
On MacOS
Step-1: Upgrade python to latest version by:
$ brew upgrade python
Step-2: Go to home:
$ cd
Step-3: open .bash_profile
$ vi .bash_profile
Setting PATH for Python 3.8
PATH="/Library/Frameworks/Python.framework/Versions/3.8/bin:${PATH}"
export PATH
Step-4: Save the file. And compile it by:
$ . .bash_profile
Step-5: Check the python version:
$ python -V
Step-6: Thats all.
This is the simplest way from my exp. (if you have brew installed on your mac).
Try this from your terminal:
brew install python3
and then run the below on your terminal :
ls -l /usr/local/bin/python*
Tip:
** (note down the python version 3.8 or 3.9 thats displayed on the terminal. This will be required in the next step). for e.g. in my case it was:
lrwxr-xr-x 1 user admin 24 May 7 14:33 /usr/local/bin/python -> /usr/local/bin/python3.9
Now run the below command on your terminal:
ln -s -f /usr/local/bin/python3.9 /usr/local/bin/python
(where 3.9 is the version displayed on your terminal with the previous command)
Its DONE !
To test your default version of python:
close the current terminal or start a new terminal and
run the below command :
python --version
Happy Coding!
I'm not sure if this is available on OS X, but on linux I would make use of the module command. See here.
Set up the modulefile correctly, then add something like this to your rc file (e.g. ~/.bashrc):
module load python3.3
This will make it so that your paths get switched around as required when you log in without impacting any system defaults.
For me the solution was using PyCharm and setting the default python version to the the one that i need to work with.
install PyCharm and go to file ==> preferences for new project, then choose the interpreter you want for your projects, in this case python 3.3
If you use macports, you do not need to play with aliases or environment variables, just use the method macports already offers, explained by this Q&A:
How to: Macports select python
TL;DR:
sudo port select --set python python27
If you are using a virtualenvwrapper, you can just locate it using which virtualenvwrapper.sh, then open it using vim or any other editor then change the following
# Locate the global Python where virtualenvwrapper is installed.
if [ "${VIRTUALENVWRAPPER_PYTHON:-}" = "" ]
then
VIRTUALENVWRAPPER_PYTHON="$(command \which python)"
fi
Change the line VIRTUALENVWRAPPER_PYTHON="$(command \which python)" to VIRTUALENVWRAPPER_PYTHON="$(command \which python3)".
If you are using macports, that has a easier way to do:
run:
port install python37
after install, set default:
sudo port select --set python python37
sudo port select --set python3 python37
restart your cmd window, finished.
Well... It's kinda old. But still deserves a good answer.
And the good one is You Don't Wanna Touch The Default Python On Mac.
Install any Python version you need via Homebrew or whatever and use it in virtualenv. Virtualenv is often considered to be something crap-like, but it's still way, wayyyy better than changing python version system-wide (macOS is likely to protect itself from such actions) or user-wide, bash-wide... whatever. Just forget about the default Python. Using playgrounds like venv is what your OS will be most, very most grateful for.
The case is, for example, many modern Linux distributions get rid of Python2 installed out-of-the-box, leaving only Python3 in the system. But everytime you try to install something old with python2 as a dependency... hope you understand what I mean. A good developer doesn't care. Good developers create clean playgrounds with python version they desire.
I have an old computer with dozens of old python projects installed, each with its own different virtualenv, and many of which built with different versions of python.
I'd prefer not to have to download these different versions when I create new virtualenvs via virtualenv -p whatever path that version of python has
My question is: within a virtualenv, is there a command I can run to find the path to the version of python which was used to create that particular environment?
For example, if I created a venv with 'virtualenv -p /usr/bin/python3.4' and then ran this command with the venv activated, it would return '/usr/bin/python3.4'
Since virtualenv copies python completely (including the binary) there is no way to know the exact path it originated from.
However, you can easily find the version by running ./python --version inside the environment's bin folder.
You could try running something like this from the command line:
python -c "import sysconfig; print(sysconfig.get_config_var('BINDIR'))"
I installed python2.x and python3.x using homebrew and the executable python paths are listed below:
$ which python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
$ which python3
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
It's quite too long and not so clean to write a shebang in a python code to make it runnable on Terminal:
#!/Library/Frameworks/Python.framework/Versions/2.7/bin/python OR
#!/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
I prefer
#!/usr/bin/python OR
#!/usr/bin/python3
My issue here is, how can I correcly move or reinstall python on macOS to /usr/bin such as /usr/bin/python OR /usr/bin/python3 Instead of
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
/Library/Frameworks/Python.framework/Versions/3.5/bin/python3
This is NOT possible on Mac OS X El Capitan anymore as from then on System Integrity Protection prevents that. More info in Cannot create a symlink inside of /usr/bin even as sudo
Create a symbolic link in /usr/bin/
Open terminal and do:
$ sudo ln /Library/Frameworks/Python.framework/Versions/2.7/bin/python /usr/bin/python
$ sudo ln /Library/Frameworks/Python.framework/Versions/3.5/bin/python3 /usr/bin/python3
You can now do what you wanted to do.
Edit: Unfortunately as you can read from the other answers, this solution no longer works on MacOS >= El Capitan due to System Integrity Protection. (See here)
A possible alternative is to use the folder /usr/local/bin that should be accessible.
The basic question in the OP seems to not be doable because the newer Mac OSes have "System Integrity Protection" which prevents "unauthorized" changes to key directories such as /usr/bin, and sudo cannot override that.
The suggestion of using /usr/local/bin and /usr/local/Frameworks seems like it should work (I haven't tried it). However, at https://opensource.com/article/19/5/python-3-default-mac, Matthew Broberg suggests that it is likely to create problems when updating.
In that same article, Moshe Zadka recommends using pyenv to manage Python environments and using shell aliases rather than symlinks.
I was going to go with the /usr/local suggestion above, but having found this contraindication, I'm going to try Moshe's method. I'll report back here if I hit any snags.
Update: I followed the method and I still was getting pip not found and which python and python -V were not giving me the expected results. Doh! I ran:
. ~/.bash_profile
(where I had put the recommended eval "$(pyenv init -)" command) and suddenly everything was finding the paths and versions as expected.
I recently came across this in a cron script at my place of work:
/bin/bash -c "[[ -s $HOME/.pythonbrew/etc/bashrc ]] && source $HOME/.pythonbrew/etc/bashrc && pythonbrew use 2.6.7 && pythonbrew venv use someapp && python /opt/someapp/bin/someapp.py"
This is for a system-wide (multi-user) installation of Pythonbrew.
It works. But please tell me there's a better way.
Addendum
To clarify what I'm looking for: I'd like a one-line command to run my script though a virtualenv tied to pythonbrew. With virtualenv alone, I could do something like this:
/opt/someapp/venv/bin/python /opt/someapp/bin/someapp.py
What I don't want is another script to run my script (like that cron command above).
I believe it can be done by using the python binary directly from you pythonbrew virtual environment.
By default its in ~/.pythonbrew/venvs/Python-<version>/<name of venv>/bin/python
But I think you can change the path with an environmental variable.
So just change the first half of the line you added to reference the pythonbrew virtual environment python binary and it should work.
On the first line on your python script add a shebang (#!) followed by a path to your target python. Then make the python script executable. It can then be executed directly from the command line (crontab, another bash script, whatever).
make a virtual env in your temp dir:
$ cd /tmp
$ virtualenv venv
the path to your python in that venv is /tmp/venv/bin/python
Using an editor create a simple script containing all of the following:
#!/tmp/venv/bin/python
print("hello world")
Save it in your home directory as "mypyscript.py"
make it executable:
$ chmod 755 mypyscript.py
Now you should be able to execute it using the filename directly on the command line:
$ ./mypyscript.py
hello world
Do this to your someapp.py substituting the relevant path to your python and that should work.
The trick turned out to be locating the pythonbrew virtualenv's python binary. Mark's answer pointed me in the right direction. But here's a complete rundown for future reference:
With pythonbrew installed, I did the following (as root on the server):
pythonbrew install 2.6.6
pythonbrew switch 2.6.6
pythonbrew venv create --no-site-packages myapp
I had a pip freeze file, so I set up my virtualenv using that:
/usr/local/pythonbrew/venvs/Python-2.6.6/myapp/bin/pip install -r /tmp/requirements.pip
Now my python binary can be found at /usr/local/pythonbrew/venvs/Python-2.6.6/myapp/bin/python. So to run my script:
/usr/local/pythonbrew/venvs/Python-2.6.6/myapp/bin/python /opt/myapp/bin/myapp.py