OSX: using bash to search python is different than using / usr / bin / env python

I don’t know what to do with it. If I ask my shell (bash) to run python without specifying the exact path, it somehow starts the wrong program (or maybe the right program, but with the wrong dylib loading). However, the result of which python and /usr/bin/env python looks very good.

Here is an illustration of what I'm talking about:

OK, first of all, where is my python command python ? Let symbolic links follow. (BTW, Too bad readlink -f and realpath do not exist on OSX ...)

 $ which python /usr/local/bin/python $ ls -l /usr/local/bin/python lrwxr-xr-x 1 root wheel 68 Jan 18 11:44 /usr/local/bin/python@ -> ../../../Library/Frameworks/Python.framework/Versions/2.7/bin/python $ ls -l /Library/Frameworks/Python.framework/Versions/2.7/bin/python lrwxr-xr-x 1 root admin 7 Jan 18 11:44 /Library/Frameworks/Python.framework/Versions/2.7/bin/python@ -> python2 $ ls -l /Library/Frameworks/Python.framework/Versions/2.7/bin/python2 lrwxr-xr-x 1 root admin 9 Jan 18 11:44 /Library/Frameworks/Python.framework/Versions/2.7/bin/python2@ -> python2.7 $ ls -l /Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 -rwxrwxr-x 1 root admin 25624 Dec 5 15:57 /Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7* 

If I call /usr/local/bin/python , where does python itself think it is? And what version?

 $ /usr/local/bin/python -c "import sys; print sys.executable; print sys.version_info" /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python sys.version_info(major=2, minor=7, micro=11, releaselevel='final', serial=0) 

OK, it looks legal. Instead of typing /usr/local/bin/python , what if I let /usr/bin/env find python for me?

 $ /usr/bin/env python -c "import sys; print sys.executable; print sys.version_info" /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python sys.version_info(major=2, minor=7, micro=11, releaselevel='final', serial=0) 

Same. So far no surprises. Ok, what if I just type python ? It should be the same as /usr/bin/env python , right?

 $ python -c "import sys; print sys.executable; print sys.version_info" /usr/local/bin/python sys.version_info(major=2, minor=7, micro=10, releaselevel='final', serial=0) 

Wait what? sys.executable points to a symbolic link , and the version is incorrect. What's happening?

Why would you print python any way from the input /usr/local/bin/python ?

BTW:

  • I double-checked bash aliases, and python not one of them. ( alias | grep python )
+1
python bash macos
Jan 18 '16 at 17:58
source share
2 answers

Bash stores a cached lookup table in memory, which you can check with hash . If you add the program to your PATH with the same name as the program you used earlier in another place, bash will still remember the old location. env explicitly bypasses this cache; or you can remove it with hash -r python .

Also note that which is intolerable and often not the right tool to use; type is specified by POSIX and is built into any modern shell.

+2
Jan 18 '16 at 18:17
source share

When you run a program from $PATH (for example, $ python ), then argv[0] set only for its name (for example, python ), and not for the full path. And the python version 2.7 of the sys.executable version looks like $PATH if argv[0] does not have a backslash at the start (for example, when you run it, as in the last example). And it seems that it does not allow symbolic links, it simply prints the first path found.

As we can see in python code , in OS X it uses NSGetExecutablePath for itself in $PATH . And on Apple say NSGetExecutablePath

That is, the path may be a symbolic link, and not a real file.

+2
Jan 18 '16 at 18:14
source share



All Articles