Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do some of CPython's lib modules have implementations in C and Python?

Tags:

python

cpython

I'm trying to adapt some code from the standard library and as I was looking through functools I noticed lines like this after each "functool":

try:
    from _functools import _lru_cache_wrapper
except ImportError:
    pass

From functools.py

In the comment header I noticed this disclaimer:

# Python module wrapper for _functools C module
# to allow utilities written in Python to be added
# to the functools module.

I then noticed that in the functools c module there are implementations for the same modules, lru_cache even talks about differences between them:

/* lru_cache object **********************************************************/

/* There are four principal algorithmic differences from the pure python version:
   1). The C version relies on the GIL instead of having its own reentrant lock.
   2). The prev/next link fields use borrowed references.
   3). For a full cache, the pure python version rotates the location of the
       root entry so that it never has to move individual links and it can
       limit updates to just the key and result fields.  However, in the C
       version, links are temporarily removed while the cache dict updates are
       occurring. Afterwards, they are appended or prepended back into the
       doubly-linked lists.
   4)  In the Python version, the _HashSeq class is used to prevent __hash__
       from being called more than once.  In the C version, the "known hash"
       variants of dictionary calls as used to the same effect.
*/

Presumably the import above just means we just import the C version. Why is there a Python implementation at all if it's just going to be overwritten? I would assume this is in case an environment can't import the C version, but what kind of CPython interpreter can't import a C module?

like image 758
mas Avatar asked Jan 28 '26 11:01

mas


1 Answers

This is required by PEP 399:

Starting in Python 3.3, any modules added to the standard library must have a pure Python implementation.

From Rationale:

Python has grown beyond the CPython virtual machine (VM). IronPython, Jython, and PyPy are all currently viable alternatives to the CPython VM.
...
The purpose of this PEP is to minimize this duplicate effort by mandating that all new modules added to Python’s standard library must have a pure Python implementation unless special dispensation is given. This makes sure that a module in the stdlib is available to all VMs and not just to CPython (pre-existing modules that do not meet this requirement are exempt, although there is nothing preventing someone from adding in a pure Python implementation retroactively).

The "overwrite pure python implementation" pattern is also metioned:

The common pattern to access the accelerated code from the pure Python implementation is to import it with an import *, e.g., from _warnings import *. This is typically done at the end of the module to allow it to overwrite specific Python objects with their accelerated equivalent

like image 141
belkka Avatar answered Jan 31 '26 01:01

belkka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!