Skip to content

v0.0.54 R03, what import does

Choose a tag to compare

@tamnd tamnd released this 05 Sep 21:02
· 6 commits to main since this release
v0.0.54
a02ad6b

R03, the third of the nine runtime lessons, and the one that takes import apart. It is not a keyword doing something the language will not explain. It compiles to a call to an ordinary builtin, that builtin is written in Python in a file you can open, and every step it takes is reachable from inside the language.

Ten cells, and each one watches rather than describes. The four spellings of the statement compiled and read back opcode by opcode, which settles that import a.b binds a and that a relative import is the empty string at a level above zero. A finder put on the front of sys.meta_path that answers nothing and writes down every question, turning one statement into three visible searches, outermost first. The three finders asked for the same three names side by side. A circular import in a temporary directory, caught reading a module halfway through its own body. A module served out of a string by fourteen lines of class, with no file on disk anywhere. The three caches an import passes through, including the one that keeps a directory you have just created invisible.

The facts worth keeping. IMPORT_NAME looks __import__ up in builtins every single time, which is why replacing it works. A dotted import is one search per part, and everything after the first part is looked for in the parent package's __path__ rather than on sys.path. A name can have more than one answer and the earlier finder wins, so import os never opens os.py, because FrozenImporter gets asked before PathFinder. The module object goes into sys.modules before its body runs, which is both why circular imports work at all and exactly what decides how much of a half loaded module the other side can see, and if the body raises the entry is taken back out again.

Two Tier 1 recordings settle the import lock, which almost everybody has wrong. It is one lock per module name and has been since 3.3, not one lock for the process. Four threads importing four different modules keep 1.02 cores busy on a release build and 3.63 on a free threaded one, so what serialises them is the GIL. Four threads importing the same module keep almost exactly one core busy on both builds and the body runs once, which is the per module lock doing its job.

Four new glossary terms: module spec, meta path finder, path entry finder and module lock. Six diagrams and seventeen citations. Both READMEs updated. GLOSSARY.md is 222 terms and CLAIMS.md is 580 claims across 74 lessons.

All ten cells also run end to end in a browser with nothing skipped, which no earlier R lesson managed.