Add R01, before your first line - #178
Merged
Merged
Conversation
The first runtime lesson. Everything so far has been about what happens when your code runs. This one is about what has already happened by the time it starts. Eight cells, every one of them asking a child interpreter rather than the notebook, because a notebook is far too late to be a fair witness about its own startup. A count of sys.modules split by where each module came from, with and without site. -X importtime adding up every import that runs before the first line. Seven children disagreeing about sys.flags.optimize. The whole path configuration printed with an exists check next to each entry. sys.path[0] compared across -c, a script, -m and -P. And ten timed starts of an interpreter that runs nothing. The facts worth having. With site out of the way, none of the modules loaded at startup were read from a file, because they are either C compiled into the binary or Python bytecode frozen into it. Startup is two halves on purpose and the first half has no import system, which is why a configuration mistake is a fatal error with a C string rather than a traceback. The command line and the environment settle a disagreement by taking the higher number rather than the nearer one, so PYTHONOPTIMIZE=2 survives a later -O. sys.path is produced by a Python program frozen into the binary and handed eleven C functions to stand in for the os.path it cannot import. And the front of sys.path is pushed on after startup is over, which is the whole mechanism behind a local random.py shadowing the standard library. Two Tier 1 recordings, the first release against debug pair in the book. The debug build starts in 56.5 ms against 26.5 ms, and the interesting part is that most of the extra is not the assertions. Release reports 17 frozen modules and none from a file. Debug reports 3 frozen and 14 from a file, because a debug build turns frozen modules off in the defaults so that you can step through the real Lib/os.py. The import bill goes from 11.6 ms to 30.8 ms with it. Three glossary terms in a new startup group: two phase initialisation, path configuration and safe path. Six diagrams. Sixteen citations. Part of #27.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first of the runtime lessons, and a change of subject. Everything up to here has been about what happens when your code runs. This one is about everything that has already happened by the time it starts.
How it is put together
Eight cells, and every one of them starts a child interpreter and asks it a question rather than looking at the notebook it is running in. That is not a stylistic choice. The notebook finished starting up long ago and has since imported hundreds of modules that have nothing to do with the subject, so it cannot be a witness about its own startup. All eight cells check whether they can start a process at all and say so rather than failing, which is what makes the lesson read through in a browser tab.
What is in it
The inventory. A child counts its own
sys.modulesand splits it by where each module came from: C compiled into the binary, Python bytecode frozen into the binary, or a path, which means somebody opened a file. With-Sthere are 21 modules and not one of them was read from a file. The cell also names the ones that did come from a file on a normal start, which on most installs is whateversitebrought in for you rather than anything the interpreter needed.The two halves. Prose, with the chain from
pymain_mainthroughpymain_initandPy_InitializeFromConfigtoPy_RunMain. Core startup builds the runtime and the built in types with no import system, nosys.pathand no codecs. Main startup is everything that needs those, including working outsys.path. That split is why a configuration mistake comes out as a fatal error with a plain C string: at the moment it is noticed there is nothing to raise. Then-X importtimein a child, which prints exactly the imports that happen before your first line and nothing else.The configuration. Seven children with different combinations of
PYTHONOPTIMIZE,-O,-OOand-E, all reportingsys.flags.optimize. The natural guess is that the command line beats the environment because it is nearer, and it is wrong. The helper that reads a flag out of the environment isif (*flag < value) *flag = value;, which raises a floor and never lowers anything, and-Oon the command line increments rather than assigns. So the answer is the highest number anybody asked for.PYTHONOPTIMIZE=2left in a shell profile is not undone by passing-Otoday, and nothing tells you.-Eis the only way out, and it works by deleting the environment rather than outranking it.The path.
sys.pathis not computed in C. It is computed byModules/getpath.py, compiled to bytecode when CPython is built, stored in the binary as a marshalled blob, unmarshalled during main startup and evaluated. It cannot import anything, becausesys.pathis what it exists to produce, so it is handed eleven C functions to stand in foros.path: abspath, basename, dirname, hassuffix, isabs, isdir, isfile, isxfile, joinpath, readlines, realpath. The cell prints the whole path configuration with anexistscheck next to every entry, which makes thepythonXY.zipthat is not there stand out. That entry is deliberate, not leftover.The front of the path.
sys.path[0]compared across-c, a script,-mand-P. It is pushed on after startup is finished, by the code that is about to hand control to your program, and it is the directory of your script or the current directory. That is the complete mechanism behind a file calledrandom.pynext to your script shadowing the standard library.-Pdoes not remove the entry, it never adds it, sosys.path[0]becomes that zip file instead.The cost. Ten timed starts of an interpreter that runs nothing, with and without
site.The recordings
Two Tier 1 recordings, and the first release against debug pair in the book. Same program, same image pipeline, one build configured with
--with-pydebug.The debug build starts in 56.5 ms against 26.5 ms. The easy explanation is the assertions and the reference count bookkeeping, and the easy explanation is mostly wrong. Release reports 17 frozen modules and 0 from a file. Debug reports 3 frozen and 14 from a file. That is not the same work done more slowly, it is different work. A debug build turns frozen modules off in the defaults, one
#ifdef, so that somebody debugging CPython steps through the realLib/os.pyrather than through bytecode baked in at build time. The import bill goes from 11.6 ms to 30.8 ms with it, and-X frozen_modules=onputs it back.Also
A new glossary group for startup and shutdown with three terms: two phase initialisation, path configuration, safe path. GLOSSARY.md is now 216 terms. Six diagrams, sixteen citations, both READMEs updated, CLAIMS.md is 564 claims across 72 lessons.
just checkandjust versionsare green locally, 167 declared and 181 noted across 72 notebooks, and the browser probe has been rerun. All eight R01 cells report that the runtime cannot start another interpreter and carry on.Part of #27.