Execution Model
Structure of a Program
A Python program is constructed from code blocks. A block is a piece of Python program text that is executed as a unit. The following are blocks:- A module
- A function body
- A class definition
- Each command typed interactively
- A script file
- A script command (specified with the
-coption) - A module run as a top level script (with the
-moption) - The string argument passed to
eval()andexec()
Naming and Binding
Binding of Names
Names refer to objects. Names are introduced by name binding operations. The following constructs bind names:- Formal parameters to functions
- Class definitions
- Function definitions
- Assignment expressions
- Targets that are identifiers if occurring in an assignment:
forloop header- After
asin awithstatement,exceptclause,except*clause, or in the as-pattern in structural pattern matching - In a capture pattern in structural pattern matching
importstatementstypestatements- Type parameter lists
import statement of the form from ... import * binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level.
If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal or global. If a name is bound at the module level, it is a global variable. If a variable is used in a code block but not defined there, it is a free variable.
Resolution of Names
A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name. When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment. When a name is not found at all, aNameError exception is raised. If the current scope is a function scope, and the name refers to a local variable that has not yet been bound to a value at the point where the name is used, an UnboundLocalError exception is raised.
The global Statement
The global statement causes the listed identifiers to be interpreted as globals:
global statement applies to the entire current scope. If a name occurs in a global statement within a block, all uses of the name within the block are treated as references to the global binding of that name.
The nonlocal Statement
The nonlocal statement causes corresponding names to refer to previously bound variables in the nearest enclosing function scope:
SyntaxError is raised at compile time if the given name does not exist in any enclosing function scope.
Annotation Scopes
Annotations, type parameter lists andtype statements introduce annotation scopes, which behave mostly like function scopes, but with some exceptions.
Annotation scopes are used in the following contexts:
- Function annotations
- Variable annotations
- Type parameter lists for generic type aliases
- Type parameter lists for generic functions
- Type parameter lists for generic classes
- The bounds, constraints, and default values for type parameters (lazily evaluated)
- The value of type aliases (lazily evaluated)
- Annotation scopes have access to their enclosing class namespace
- Expressions in annotation scopes cannot contain
yield,yield from,await, or:=expressions - Names defined in annotation scopes cannot be rebound with
nonlocalstatements in inner scopes - The internal name is not reflected in the qualified name of objects defined within the scope
Lazy Evaluation
Most annotation scopes are lazily evaluated. This includes annotations, the values of type aliases created through thetype statement, and the bounds, constraints, and default values of type variables created through the type parameter syntax.
This means that they are not evaluated when the type alias or type variable is created, but only when necessary:
Builtins and Restricted Execution
The builtins namespace associated with the execution of a code block is actually found by looking up the name__builtins__ in its global namespace; this should be a dictionary or a module (in the latter case the module’s dictionary is used).
By default, when in the __main__ module, __builtins__ is the built-in module builtins; when in any other module, __builtins__ is an alias for the dictionary of the builtins module itself.
Exceptions
Exceptions are a means of breaking out of the normal flow of control of a code block in order to handle errors or other exceptional conditions. An exception is raised at the point where the error is detected; it may be handled by the surrounding code block or by any code block that directly or indirectly invoked the code block where the error occurred. The Python interpreter raises an exception when it detects a run-time error (such as division by zero). A Python program can also explicitly raise an exception with theraise statement. Exception handlers are specified with the try ... except statement.
SystemExit.
Exceptions are identified by class instances. The except clause is selected depending on the class of the instance: it must reference the class of the instance or a non-virtual base class thereof. The instance can be received by the handler and can carry additional information about the exceptional condition.
Exception messages are not part of the Python API. Their contents may change from one version of Python to the next without warning and should not be relied on by code which will run under multiple versions of the interpreter.
Runtime Components
General Computing Model
Python’s execution model does not operate in a vacuum. It runs on a host machine and through that host’s runtime environment, including its operating system. When a program runs, the conceptual layers look like this:Python Runtime Model
The same conceptual layers apply to each Python program, with some extra data layers specific to Python:sys.modules.
For thread-specific runtime state, each interpreter has a set of thread states, which it manages. Each thread state has all the thread-specific runtime data an interpreter needs to operate in one host thread. The thread state includes the current raised exception and the thread’s Python call stack.
Each thread state, over its lifetime, is always tied to exactly one interpreter and exactly one host thread. It will only ever be used in that thread and with that interpreter.