"WHY" 2 different executables of python of same version?

1k Views Asked by At

When I press tab on the command python3.7 I get the following

python3.7          python3.7-config   python3.7m         python3.7m-config

I looked up what's python3.7m and found the answer - https://stackoverflow.com/a/16677339/6849682.

Next I go to the python terminal of each implementation and type the following code

>>> import sysconfig
>>> sysconfig.get_config_var('EXT_SUFFIX')

I get the same output in both python implementations i.e .cpython-37m-darwin.so

I also tried the command diff <(python3.7 -m sysconfig) <(python3.7m -m sysconfig) to see if there's any difference in configuration info of the 2 executables but the output is empty means they are the same.

If all the executables and configuration variables are same, then why create two different implementations of python?

Note:

I'm not talking about python3.7/3.7m-config here.

2

There are 2 best solutions below

3
On

python3.7 and python3.7m are the same program, just with two different names. These two files are hard-linked, meaning they point to the same file on disk (i.e., they have the same inode).

Here is the line in the cpython 3.7 Makefile that performs this hardlink.

(cd $(DESTDIR)$(BINDIR); $(LN) python$(LDVERSION)$(EXE) python$(VERSION)$(EXE));

$(LDVERSION) would be 3.7m, and $(VERSION) would be 3.7. This is the only place in the Makefile that performs a hardlink.


The python3.7 Docker image is used below to demonstrate that python3.7 and python3.7 have the same inode.

$ docker run --rm -it python:3.7-alpine ash
/ # ls -i $(which python3.7)
 927902 /usr/local/bin/python3.7
/ # ls -i $(which python3.7m)
 927902 /usr/local/bin/python3.7m
0
On

Binary compatibility with C extensions

For a C extension to be compatible across interpreter builds, some of the build-time flags need to be identical. One of these flags is whether pymalloc (a memory-allocation library intended to be faster for Python-specific use cases) is enabled. Versions of libpython have an m suffix indicating that this flag was present at build time, when it in fact was.

If a C extension is built with pymalloc support, it can't be used by an interpreter using the standard C library's malloc(), and the inverse. Consequently, for someone who has a C extension as a prebuilt binary that was built with pymalloc, it can be useful to be able to start a Python interpreter that is known to be itself pymalloc-enabled.

If a Linux distribution chooses to only ship a pymalloc-enabled interpreter, it makes sense to have only one binary available under both python3.7 and python3.7m names. (This leaves folks who need a non-pymalloc interpreter a bit out of luck, but build tools aren't as hard to come by on Linux as they are on Windows, so ABI compatibility is not as critical).