Importing the sys module to determine the version of Python

Feedback


Solution 1:

Both @Graeme

It is possible that Python’s inability to retrieve this information indicates that it is conducting an autonomous search in its PATH.

and @twalberg

The current PATH seems to be the target of sys.executable’s search, rather than resolving argv[0]. It’s possible that this is due to argv[0] being simply python in this case.

It seems that their assumption was correct. Initially, I was hesitant to accept that Python uses a straightforward method like

PATH

to identify itself, but it turns out to be accurate.

The module for

sys

in Python is located in the

Python/sysmodule.c

file. Line 1422 of version 2.7.6 sets

sys.executable

in this manner.

 SET_SYS_FROM_STRING("executable",
                     PyString_FromString(Py_GetProgramFullPath()));

The file

Modules/getpath.c

contains a function that begins on line 701 with the identifier

Py_GetProgramFullPath()

.

char *
Py_GetProgramFullPath(void)
{
    if (!module_search_path)
        calculate_path();
    return progpath;
}

The file where

calcuate_path()

function is defined has a comment associated with it.

/* If there is no slash in the argv0 path, then we have to
 * assume python is on the user's $PATH, since there's no
 * other way to find a directory to start the search from.  If
 * $PATH isn't exported, you lose.
 */

My experience shows that if the Python code being exported as

$PATH

is not the same as the one being executed, one can also experience loss.

Additional details regarding how the interpreter’s executable placement is calculated can be located in the header of the

getpath.c

document.

The executable’s location is determined before searching. If argv[0] contains slashes, it is utilized as is. If not, we check $PATH for the executable’s name and use it if found. If $PATH does not have the executable (or if there is no $PATH environment variable), we use the original argv[0] string.

The program checks if the executable location is a symbolic link, and if it is, it correctly follows the link (taking into account any relative pathnames) and utilizes the directory of the link target.

We can perform a few tests to confirm the information stated above.

The value of argv[0] remains unaltered if it contains one or more slashes.

[user@localhost ~]$ sudo /usr/local/bin/python what_python.py
/usr/local/bin/python
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]

Ok.

In case the $PATH environment variable is missing or the executable cannot be located on it, the initial argv[0] string is utilized.

[user@localhost ~]$ sudo PATH= python what_python.py

2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]

According to the documentation of the sys module, the statement stating that sys.executable will be an empty string or None if Python can’t fetch the actual path to its executable is correct in this scenario.

We’ll check if the problem can be resolved by reinstating the location of Python’s binary to

PATH

after it was removed by sudo.

[user@localhost ~]$ sudo PATH=$PATH python what_python.py
/usr/local/bin/python
2.7.6 (default, Feb 27 2014, 17:05:07) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]

It does.

Related:

  • The location of sys.executable is incorrect when the zeroth command argument is altered in Python issue 7774.
  • Concerning Python problem 10835, the default for sys.executable and altinstall are being examined.
  • Discussion on the python-dev email thread regarding a more precise explanation of sys.executable.
  • How can the executable’s location be identified in C, as asked in a Stackoverflow question?


Solution 2:


I believe that the executable being executed is

/usr/local/bin/python

. Considering that the version string is most likely integrated into

python

, it is highly improbable for it to be inaccurate. Upon reviewing the documentation of

sys.executable

:

sys.executable

On systems where applicable, sys.executable provides a string that presents the complete path of the Python interpreter’s executable binary. If the actual path cannot be obtained by Python, sys.executable will either be an empty string or None.

It appears that

python

cannot access the information, implying that it conducts an individual search using

PATH

under the sudo has set. It is important to note that this is distinct from the search it performed to locate the executable, as explained in my response to the previous question.

To ensure accuracy, it’s necessary to analyze the python implementation. Generally, it’s more reliable to trust the version string. However,

sudo

utilizes

execve

for executing the command, as stated in the

man

page. When using

execve

, the full path of the executable must be specified, since this particular variation doesn’t conduct its own search, unlike some of the other

exec

variations. Therefore, it should be simple for

python

to complete

sys.executable

.

It is unclear whether the

argv[0]

for the

python

interpreter can be obtained directly. Typically, the

sys.argv[0]

identifies the name of the script or

-c

. Nevertheless, it would be intriguing to investigate this possibility. In the event that it is not available (

/usr/local/bin/python

), it could indicate a flaw in

python

.

To achieve consistency, my suggestion is to simply place the

secure_path

within

/etc/sudoers

.

Update

The program

execve

requires two arguments: the executable path and an

argv

array. Therefore,

argv[0]

may not always be

/usr/local/bin/python

. However, you can determine its value by creating a script as follows:

import time
time.sleep(60)

Execute the code and retrieve the complete parameters by obtaining

ps

.

sudo python sleep.py &
ps -o args= -C python

To confirm the

python

being executed, you can utilize the following method.

sudo ls -l /proc/PID/exe

while the program is running.


Solution 3:


On each occasion of launching the Python interpreter, the shell directs to /usr/bin/python and runs it (you can verify this by using the command: python -c “import os; print(os.environ[‘_’])”).

As evident,

ln -l | grep python

the python interpreter executable is linked to /usr/bin/python as a soft link.

What I did was:

  1. Obtain the latest version of Python by visiting the official website of Python, downloading the most recent code, and implementing it by utilizing

    configure && make && make install

    .
  2. Verify the whereabouts of the most recent version’s executable file.
  3. To remove the soft link for /usr/bin/python, root permission is required and the command to use is “sudo”.
  4. The executable for the latest version of Python can be found at

    ln -s <location

    . It is probable that sudo privileges will be necessary to access it.
  5. Run Python using the terminal.
  6. import sys

The final version of sys should be utilized.

Frequently Asked Questions