Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Python find the value for sys.prefix (resp. sys.base_prefix)?

Tags:

python

unix

What is says on the tin.

I have solved the mystery of how sys.prefix gets set when using a virtual environment (Python looks for a pyvenv.cfg file [1]).

However, I don't understand exactly how Python finds sys.base_prefix.
The default is /usr/local (on Unix) [2].
However, that doers not seem to be in effect on my Mac.

As the code below shows, symlinks are followed, and in this case the sys.base_prefix is simply the directory above the actual Python binary:

# Following symlinks to determinw where the actual hard link is
➜  tmp ls -l /usr/local/bin/python3
lrwxr-xr-x  1 jeffhemmen  admin  38 23 Jul 12:23 /usr/local/bin/python3 -> ../Cellar/[email protected]/3.8.5/bin/python3
➜  tmp ls -l /usr/local/Cellar/[email protected]/3.8.5/bin/python3
lrwxr-xr-x  1 jeffhemmen  staff  55 20 Jul 14:26 /usr/local/Cellar/[email protected]/3.8.5/bin/python3 -> ../Frameworks/Python.framework/Versions/3.8/bin/python3
➜  tmp ls -l /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3
lrwxr-xr-x  1 jeffhemmen  staff  9 20 Jul 14:26 /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3 -> python3.8
➜  tmp ls -l /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8
-rwxr-xr-x  1 jeffhemmen  staff  17704 23 Jul 12:23 /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8
# Printing sys.base_prefix for all these links
➜  tmp /usr/local/bin/python3 -c "import sys; print(sys.base_prefix)" 
/usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8
➜  tmp /usr/local/Cellar/[email protected]/3.8.5/bin/python3 -c "import sys; print(sys.base_prefix)"  
/usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8
➜  tmp /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8
➜  tmp /usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8/bin/python3.8 -c "import sys; print(sys.base_prefix)"
/usr/local/Cellar/[email protected]/3.8.5/Frameworks/Python.framework/Versions/3.8

However, in the example below (same computer, my Mac), the sys.base_prefix is completely different:

➜  tmp ls -l /usr/bin/python3 
-rwxr-xr-x  1 root  wheel  31488 10 Aug 21:56 /usr/bin/python3
➜  tmp /usr/bin/python3 -c "import sys; print(sys.base_prefix)" 
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7

I have read somewhere that this depends on how Python was installed. Does this mean the sys.base_prefix is actually compiled into the binary? If not is there a text file (config, .py, ...) somewhere that Python reads upon startup?

Bonus question: when/how/why is sys.exec_prefix actually different from sys.prefix (and/or sys.base_exec_prefix from sys.base_prefix`)?

like image 666
Jeff Hemmen Avatar asked Nov 06 '22 04:11

Jeff Hemmen


1 Answers

The documentation explains how the values are set and how a virtual environment overrides it.

Here is the source code for the sys module, and it seems to be set at initialization from the interpreter state. I didn't follow that path further.

like image 170
Frank Yellin Avatar answered Nov 14 '22 03:11

Frank Yellin