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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With