> **Источник:** https://python-all.ru/3.4/reference/executionmodel.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 4. Модель выполнения

## 4.1. Структура программы

Программа на Python состоит из блоков кода. A *Блок* – это часть текста программы на Python, которая выполняется как единое целое. Блоками являются: модуль, тело функции и определение класса. Каждая команда, введённая в интерактивном режиме, является блоком. Файл сценария (файл, переданный в качестве стандартного ввода интерпретатору или указанный как аргумент командной строки интерпретатора) является блоком кода. Команда сценария (команда, указанная в командной строке интерпретатора с опцией ‘**-c**‘) является блоком кода. Строковый аргумент, передаваемый встроенным функциям [`eval()`](https://python-all.ru/3.4/library/functions.html#eval) и [`exec()`](https://python-all.ru/3.4/library/functions.html#exec), является блоком кода.

Блок кода выполняется в *фрейме выполнения*. Фрейм содержит некоторую служебную информацию (используемую для отладки) и определяет, где и как продолжится выполнение после завершения выполнения блока кода.

## 4.2. Именование и связывание

### 4.2.1. Связывание имён

*Имена* ссылаются на объекты. Имена вводятся операциями связывания имён.

Следующие конструкции связывают имена: формальные параметры функций, [`import`](https://python-all.ru/3.4/reference/simple_stmts.html#import) инструкции, определения классов и функций (они связывают имя класса или функции в определяющем блоке), а также цели, являющиеся идентификаторами, если они встречаются в присваивании, заголовке цикла [`for`](https://python-all.ru/3.4/reference/compound_stmts.html#for) или после [`as`](https://python-all.ru/3.4/reference/compound_stmts.html#as) в инструкции [`with`](https://python-all.ru/3.4/reference/compound_stmts.html#with) или предложении [`except`](https://python-all.ru/3.4/reference/compound_stmts.html#except). Инструкция [`import`](https://python-all.ru/3.4/reference/simple_stmts.html#import) вида `from ... import *` связывает все имена, определённые в импортированном модуле, кроме тех, которые начинаются с подчёркивания. Эта форма может использоваться только на уровне модуля.

Цель, встречающаяся в инструкции [`del`](https://python-all.ru/3.4/reference/simple_stmts.html#del), также считается связанной для этих целей (хотя фактическая семантика – отвязать имя).

Каждый оператор присваивания или импорта находится внутри блока, определённого классом или определением функции, либо на уровне модуля (блок кода верхнего уровня).

Если имя связано в блоке, оно является локальной переменной этого блока, если не объявлено как [`nonlocal`](https://python-all.ru/3.4/reference/simple_stmts.html#nonlocal) или [`global`](https://python-all.ru/3.4/reference/simple_stmts.html#global). Если имя связано на уровне модуля, оно является глобальной переменной. (Переменные блока кода модуля являются локальными и глобальными.) Если переменная используется в блоке кода, но не определена в нём, она является *свободной переменной*.

Каждое вхождение имени в тексте программы ссылается на *связывание* этого имени, установленное следующими правилами разрешения имён.

### 4.2.2. Разрешение имён

*Область видимости* определяет видимость имени внутри блока. Если локальная переменная определена в блоке, её область видимости включает этот блок. Если определение находится в функциональном блоке, область видимости распространяется на любые блоки, вложенные в определяющий, если вложенный блок не вводит другое связывание для этого имени.

Когда имя используется в блоке кода, оно разрешается с помощью ближайшей объемлющей области видимости. Множество всех таких областей, видимых блоку кода, называется его *окружением*.

Когда имя вообще не найдено, вызывается исключение [`NameError`](https://python-all.ru/3.4/library/exceptions.html#NameError). Если текущая область видимости – функциональная, и имя ссылается на локальную переменную, которая ещё не была привязана к значению в точке использования имени, вызывается исключение [`UnboundLocalError`](https://python-all.ru/3.4/library/exceptions.html#UnboundLocalError). [`UnboundLocalError`](https://python-all.ru/3.4/library/exceptions.html#UnboundLocalError) является подклассом [`NameError`](https://python-all.ru/3.4/library/exceptions.html#NameError).

Если операция связывания имени происходит где-либо внутри блока кода, все использования имени в блоке рассматриваются как ссылки на текущий блок. Это может привести к ошибкам, когда имя используется в блоке до того, как оно связано. Это правило тонкое. В Python нет объявлений, и операции связывания имени могут происходить в любом месте блока кода. Локальные переменные блока кода можно определить, просканировав весь текст блока на наличие операций связывания имени.

Если инструкция [`global`](https://python-all.ru/3.4/reference/simple_stmts.html#global) встречается внутри блока, все использования имени, указанного в инструкции, ссылаются на связывание этого имени в пространстве имён верхнего уровня. Имена разрешаются в пространстве имён верхнего уровня путём поиска в глобальном пространстве имён, т.е. пространстве имён модуля, содержащего блок кода, и пространстве имён builtins, пространстве имён модуля [`builtins`](https://python-all.ru/3.4/library/builtins.html#module-builtins). Глобальное пространство имён просматривается первым. Если имя не найдено там, просматривается пространство имён builtins. Инструкция [`global`](https://python-all.ru/3.4/reference/simple_stmts.html#global) должна предшествовать всем использованиям имени.

Инструкция [`global`](https://python-all.ru/3.4/reference/simple_stmts.html#global) имеет ту же область видимости, что и операция связывания имени в том же блоке. Если ближайшая охватывающая область видимости для свободной переменной содержит инструкцию global, свободная переменная рассматривается как глобальная.

Инструкция [`nonlocal`](https://python-all.ru/3.4/reference/simple_stmts.html#nonlocal) заставляет соответствующие имена ссылаться на ранее связанные переменные в ближайшей охватывающей функциональной области видимости. [`SyntaxError`](https://python-all.ru/3.4/library/exceptions.html#SyntaxError) возникает на этапе компиляции, если указанное имя не существует ни в одной охватывающей функциональной области видимости.

Пространство имён модуля автоматически создаётся при первом импорте модуля. Главный модуль сценария всегда называется [`__main__`](https://python-all.ru/3.4/library/__main__.html#module-__main__).

Блоки определения классов и аргументы [`exec()`](https://python-all.ru/3.4/library/functions.html#exec) и [`eval()`](https://python-all.ru/3.4/library/functions.html#eval) являются особыми в контексте разрешения имён. Определение класса – это исполняемая инструкция, которая может использовать и определять имена. Эти ссылки следуют обычным правилам разрешения имён, за исключением того, что несвязанные локальные переменные ищутся в глобальном пространстве имён. Пространство имён определения класса становится словарём атрибутов класса. Область видимости имён, определённых в блоке класса, ограничена этим блоком; она не распространяется на блоки кода методов – это включает генераторы списков и выражения-генераторы, поскольку они реализованы с использованием функциональной области видимости. Это означает, что следующий код завершится ошибкой:

```python
class A:
    a = 42
    b = list(a + i for i in range(10))
```

### 4.2.3. Встроенные объекты и ограниченное выполнение

Пространство имён builtins, связанное с выполнением блока кода, на самом деле находится путём поиска имени `__builtins__` в его глобальном пространстве имён; это должен быть словарь или модуль (в последнем случае используется словарь модуля). По умолчанию, когда в модуле [`__main__`](https://python-all.ru/3.4/library/__main__.html#module-__main__), `__builtins__` является встроенным модулем [`builtins`](https://python-all.ru/3.4/library/builtins.html#module-builtins); когда в любом другом модуле, `__builtins__` является псевдонимом словаря самого модуля [`builtins`](https://python-all.ru/3.4/library/builtins.html#module-builtins). `__builtins__` может быть установлен в словарь, созданный пользователем, для создания слабой формы ограниченного выполнения.

**Деталь реализации CPython:** Пользователям не следует трогать `__builtins__`; это строго деталь реализации. Пользователи, желающие переопределить значения в пространстве имён builtins, должны [`import`](https://python-all.ru/3.4/reference/simple_stmts.html#import) модуль [`builtins`](https://python-all.ru/3.4/library/builtins.html#module-builtins) и изменить его атрибуты соответствующим образом.

### 4.2.4. Взаимодействие с динамическими возможностями

Разрешение имён свободных переменных происходит во время выполнения, а не во время компиляции. Это означает, что следующий код выведет 42:

```python
i = 10
def f():
    print(i)
i = 42
f()
```

Есть несколько случаев, когда инструкции Python недопустимы при использовании в сочетании с вложенными областями видимости, содержащими свободные переменные.

Если переменная используется в охватывающей области видимости, удаление этого имени недопустимо. Ошибка будет сообщена на этапе компиляции.

Функции [`eval()`](https://python-all.ru/3.4/library/functions.html#eval) и [`exec()`](https://python-all.ru/3.4/library/functions.html#exec) не имеют доступа к полному окружению для разрешения имён. Имена могут разрешаться в локальном и глобальном пространствах имён вызывающей стороны. Свободные переменные разрешаются не в ближайшем охватывающем пространстве имён, а в глобальном. [\[1\]](https://python-all.ru/3.4/reference/executionmodel.html#id3) Функции [`exec()`](https://python-all.ru/3.4/library/functions.html#exec) и [`eval()`](https://python-all.ru/3.4/library/functions.html#eval) имеют необязательные аргументы для переопределения глобального и локального пространств имён. Если указано только одно пространство имён, оно используется для обоих.

## 4.3. Исключения

Исключения – это способ выйти из нормального потока управления блока кода, чтобы обработать ошибки или другие исключительные ситуации. Исключение *возбуждается* в том месте, где обнаружена ошибка; оно может быть *перехвачено* окружающим блоком кода или любым блоком, который прямо или косвенно вызвал блок кода, где произошла ошибка.

Интерпретатор Python вызывает исключение, когда обнаруживает ошибку времени выполнения (например, деление на ноль). Программа на Python также может явно вызвать исключение с помощью инструкции [`raise`](https://python-all.ru/3.4/reference/simple_stmts.html#raise). Обработчики исключений задаются с помощью инструкции [`try`](https://python-all.ru/3.4/reference/compound_stmts.html#try) ... [`except`](https://python-all.ru/3.4/reference/compound_stmts.html#except). Предложение [`finally`](https://python-all.ru/3.4/reference/compound_stmts.html#finally) такой инструкции можно использовать для указания кода очистки, который не обрабатывает исключение, но выполняется независимо от того, произошло исключение или нет в предшествующем коде.

В Python используется модель обработки ошибок с «завершением»: обработчик исключений может выяснить, что произошло, и продолжить выполнение на внешнем уровне, но он не может исправить причину ошибки и повторить сбойную операцию (кроме случая повторного входа в проблемный кусок кода с самого начала).

Когда исключение не обрабатывается совсем, интерпретатор завершает выполнение программы или возвращается в свой интерактивный главный цикл. В любом случае он печатает стек вызовов, за исключением случая, когда исключение является [`SystemExit`](https://python-all.ru/3.4/library/exceptions.html#SystemExit).

Исключения идентифицируются экземплярами классов. Предложение [`except`](https://python-all.ru/3.4/reference/compound_stmts.html#except) выбирается в зависимости от класса экземпляра: оно должно ссылаться на класс экземпляра или его базовый класс. Экземпляр может быть получен обработчиком и может нести дополнительную информацию об исключительной ситуации.

> **Примечание**
>
> Сообщения исключений не являются частью API Python. Их содержимое может меняться от одной версии Python к другой без предупреждения, и на него не следует полагаться в коде, который будет выполняться под несколькими версиями интерпретатора.

См. также описание инструкции [`try`](https://python-all.ru/3.4/reference/compound_stmts.html#try) в разделе [*Инструкция try*](https://python-all.ru/3.4/reference/compound_stmts.html#try) и инструкции [`raise`](https://python-all.ru/3.4/reference/simple_stmts.html#raise) в разделе [*Инструкция raise*](https://python-all.ru/3.4/reference/simple_stmts.html#raise).

Сноски

| [\[1\]](https://python-all.ru/3.4/reference/executionmodel.html#id1) | Это ограничение возникает потому, что код, который выполняется этими операциями, недоступен на момент компиляции модуля. |
| --- | --- |
