4. Execution model¶
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, and a class definition. Each command typed interactively is a block. A script file (a file given as standard input to the interpreter or specified as a command line argument to the interpreter) is a code block. A script command (a command specified on the interpreter command line with the -c option) is a code block. A module run as a top level script (as module __main__ ) from the command line using a -m argument is also a code block. The string argument passed to the built-in functions eval() and exec() is a code block.
A code block is executed in an execution frame. A frame contains some administrative information (used for debugging) and determines where and how execution continues after the code block’s execution has completed.
4.2. Naming and binding¶
4.2.1. Binding of names¶
Names refer to objects. Names are introduced by name binding operations.
The following constructs bind names:
formal parameters to functions,
targets that are identifiers if occurring in an assignment:
after as in a with statement, except clause, except* clause, or in the as-pattern in structural pattern matching,
in a capture pattern in structural pattern matching
The 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.
A target occurring in a del statement is also considered bound for this purpose (though the actual semantics are to unbind the name).
Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block).
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. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.
Each occurrence of a name in the program text refers to the binding of that name established by the following name resolution rules.
4.2.2. 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, a NameError 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. UnboundLocalError is a subclass of NameError .
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations. See the FAQ entry on UnboundLocalError for examples.
If the global statement occurs within a block, all uses of the names specified in the statement refer to the bindings of those names in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module builtins . The global namespace is searched first. If the names are not found there, the builtins namespace is searched. The global statement must precede all uses of the listed names.
The global statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains a global statement, the free variable is treated as a global.
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.
The namespace for a module is automatically created the first time a module is imported. The main module for a script is always called __main__ .
Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. The namespace of the class definition becomes the attribute dictionary of the class. The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope. This means that the following will fail:
4.2.3. Builtins and restricted execution¶
CPython implementation detail: Users should not touch __builtins__ ; it is strictly an implementation detail. Users wanting to override values in the builtins namespace should import the builtins module and modify its attributes appropriately.
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.
4.2.4. Interaction with dynamic features¶
Name resolution of free variables occurs at runtime, not at compile time. This means that the following code will print 42:
The eval() and exec() functions do not have access to the full environment for resolving names. Names may be resolved in the local and global namespaces of the caller. Free variables are not resolved in the nearest enclosing namespace, but in the global namespace. 1 The exec() and eval() functions have optional arguments to override the global and local namespace. If only one namespace is specified, it is used for both.
4.3. 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 the raise statement. Exception handlers are specified with the try … except statement. The finally clause of such a statement can be used to specify cleanup code which does not handle the exception, but is executed whether an exception occurred or not in the preceding code.
Python uses the “termination” model of error handling: an exception handler can find out what happened and continue execution at an outer level, but it cannot repair the cause of the error and retry the failing operation (except by re-entering the offending piece of code from the top).
When an exception is not handled at all, the interpreter terminates execution of the program, or returns to its interactive main loop. In either case, it prints a stack traceback, except when the exception is 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.
See also the description of the try statement in section The try statement and raise statement in section The raise statement .
This limitation occurs because the code that is executed by these operations is not available at the time the module is compiled.
Компиляция Python

Предположим, вы разработали приложение или библиотеку на Python и уже готовитесь передать его / её заказчику. И в этот момент возникают вопросы, о которых многие даже не задумываются.
Во-первых, так может оказаться, что вы разработали супер крутой алгоритм, которого ни у кого нет, и показывать его хочется только избранным.
Во-вторых, возникает вопрос окружения — хочется быть уверенным, что заказчик справится с установкой правильной версии Python и всех вспомогательных библиотек, но это не всегда простая задача. Было бы удобно упаковать приложение в автономный исполняемый файл.
И, наконец, хочется, чтобы конечное приложение работало быстрее, чем в среде разработки.
И вот тут настало время скомпилировать Python-код. Меня зовут Руслан, я старший разработчик компании «Цифровое проектирование». Сегодня я расскажу, как выбрать тот самый компилятор из множества доступных.
AOT/JIT
Компиляция – это сборка программы, включающая: трансляцию всех модулей программы, написанных на языке программирования высокого уровня, в эквивалентные программные модули на низкоуровневом языке, близком к машинному коду, или на машинном языке и сборку исполняемой программы. Существует два вида компиляции:
AOT-компиляция (ahead-of-time) – компиляция перед исполнением программы. Т.е. программа компилируется один раз, в результате компиляции получается исполняемый файл.
JIT-компиляция (just-in-time) – компиляция во время исполнения программы. Т.е. программа (а точнее, блоки программы) компилируется много раз — при каждом запуске.
Бенчмарк
Так как одной из целей является ускорение, необходимо оценить, насколько быстро работает скомпилированный код. В качестве бенчмарка будем использовать pyperfomance. К сожалению, pyperfomance не подошел для Cython и Pythran, потому что не позволяет визуализировать все возможности языка. Ускорения для Cython без модификации кода получить не удалось, а Pythran не умеет в пользовательские классы. Для них воспользуемся вычислением числа пи:
Эксперименты будем проводить на процессоре Intel Core i7 10510U. На CPython 3.9.7 время вычисления числа пи до 100.000.000 знака заняло 5.82 секунды.
AOT-компиляция Python
PyInstaller
PyInstaller упаковывает приложения Python в автономные исполняемые файлы в Windows, GNU / Linux, Mac OS X, FreeBSD, Solaris и AIX.
Устанавливается через pip:
pip install pyinstaller
После установки для создания исполняемого файла достаточно выполнить команду:
В результате будет создано:
*.spec – файл спецификации (используется для ускорения будущих сборок приложения, связи файлов данных с приложением, для включения .dll и .so файлов, добавление в исполняемый файл параметров runtime-а Python);
build/ – директория с метаданными для сборки исполняемого файла;
dist/ – директория, содержащая все зависимости и исполняемый файл.
Сборку приложения можно настроить с помощью параметров командной строки:
—name – изменение имени исполняемого файла (по умолчанию, такое же, как у сценария);
—onefile – создание только исполняемого файла (по умолчанию, папка с зависимостями и исполняемый файл);
—hidden-import – перечисление импортов, которые PyInstaller не смог обнаружить автоматически;
—add-data – добавление в сборку файлов данных;
—add-binary – добавление в сборку бинарных файлов;
—exclude-module – исключение модулей из исполняемого файла;
—key – ключ шифрования AES256. Да, приложение не будет содержать исходного кода, но его можно декомпилировать, например, так: Pyinstaller Extractor (.exe → .pyc) и uncompile6 (.pyc → .py). Для скрытия исходного кода можно обфусцировать байт-код Python с помощью шифрования.
У PyInstaller есть ограничения. Он работает с Python 3.5–3.9. Поддерживает создание исполняемых файлов для разных операционных систем, но не умеет выполнять кросскомпиляцию, т. е. необходимо генерировать исполняемый файл для каждой ОС отдельно. Более того, исполняемый файл зависит от пользовательского glibc, т. е. необходимо генерировать исполняемый файл для самой старой версии каждой ОС.
PyInstaller знает о многих Python-пакетах и умеет их учитывать при сборке исполняемого файла. Но не о всех. Например, фреймворк uvicorn практически весь нужно явно импортировать в файл, к которому будет применена команда pyinstaller. Полный список поддерживаемых из коробки пакетов можно посмотреть здесь.
Cython
Cython — это оптимизирующий статический компилятор как для языка программирования Python, так и для расширенного языка программирования Cython. С его помощью можно код на Python транслировать в С и затем скомпилировать в бинарник, совместимый с CPython. Компиляцию придется делать под все операционные системы и архитектуры процессора.
Ставится Cython через pip:
pip install Cython
Рассмотрим его работу на примере с вычислением числа пи:
Немного модифицируем нашу функцию:
Cython → C:
cython -2 pi_approximater.pyx -o pi_approximater.c
Компилируем С-шный код:
gcc -g -O2 -shared -o pi_approximater.so pi_approximater.c python-config —includes —ldflags -fPIC
И замеряем время на бенчмарке: 3,66 секунды.
А что делать, если в нашем проекте несколько файлов, которые нужно скомпилировать? Тогда нужно использовать так называемый сценарий сборки. С его помощью можно модернизировать сборку в зависимости от операционной системы, указывать несколько файлов, которые необходимо скомпилировать, и многое другое.
Создадим файл build.py:
Запустим: python build.py build_ext –-inplace
В результате будет сгенерирован .so/.dll файл.
Nuitka
Nuitka способна упаковывать приложения Python в автономные исполняемые файлы, а также транслировать Python-код в С для его последующей компиляции. Работает с разными версиями Python (2.6, 2.7, 3.3 — 3.9).
Ставится через pip:
pip install nuitka
Для генерации исполняемого файла достаточно выполнить команду:
python -m nuitka —follow-import some_program.py
Для компиляции модуля:
python -m nuitka —module some_module.py
Для компиляции пакета:
python -m nuitka —module some_package —include-package = some_package
Pythran
Pythran – статический компилятор Python, позиционирующий себя как ориентированный на научные вычисления и использующий преимущества многоядерных процессоров и блоков инструкций SIMD. Он транслирует Python-код, аннотированный описаниями интерфейса, в C++. До версии 0.9.5 (включительно) Pythran поддерживал Python 3 и Python 2.7. Последние версии поддерживают только Python 3.
pip install pythran
Генерируем бинарный файл <имя файла>.so:
pythran <имя файла>.py
Pythran по умолчанию не умеет в пользовательские классы, поэтому при попытке их компиляции будет выброшена ошибка:
Top level statements can only be assignments, strings,functions, comments, or imports
Добавим комментарий аннотации функции:
Скомпилируем и бенчмарк выдает 0,00007 секунды.
cx-Freeze
cx-Freeze – это набор скриптов и модулей преобразования скриптов Python в исполняемые файлы. cx_Freeze — кроссплатформенный. Он поддерживает Python 3.5.2 и выше.
Ставится с помощью pip:
pip install cx_Freeze
Для генерации исполняемого файла достаточно выполнить команду:
cxfreeze <имя файла>.py
Сборку можно настроить с помощью параметров командной строки:
-h, —help — справка;
-O — оптимизировать сгенерированный байт-код согласно PYTHONOPTIMIZE;
-c, —compress — сжать байт-код в zip-файлах;
-s, —silent — выводить только предупреждения и ошибки;
—target-dir=DIR, —install-dir=DIR — каталог, в который следует поместить целевой файл и все зависимые файлы.
Также возможно использование сценария сборки, например, так:
Сборка исполняемого файла:
python setup.py build
JIT-компиляция Python
JIT-компиляция не позволяет скрывать исходники или создавать автономный исполняемый файл, но дает возможность значительно ускорить выполнение программы.
PyPy
PyPy — интерпретатор языка программирования Python 2.7 и Python 3.7. Он написан на RPython и содержит:
компилятор байт-кода, отвечающий за создание объектов кода Python из исходного кода пользовательского приложения;
оценщик байт-кода, ответственный за интерпретацию объектов кода Python;
стандартное объектное пространство, отвечающее за создание и управление объектами Python, видимыми приложением.
PyPy поддерживает сотни библиотек Python, включая NumPy.
Основные особенности (сравнение с CPython):
Скорость. При выполнении длительно выполняющихся программ, когда значительная часть времени тратится на выполнение кода Python, PyPy может значительно ускорить ваш код.
Использование памяти. Программы Python, требующие много памяти (несколько сотен Мб или более), могут занимать меньше места, чем в CPython. Однако это не всегда так, поскольку зависит от множества деталей. Также базовый уровень потребления оперативной памяти выше, чем у CPython.
Скачать PyPy можно с здесь. После скачивания PyPy готов к запуску после распаковки архива. Если необходимо сделать PyPy доступным для всей системы, достаточно поместить символическую ссылку на исполняемый файл pypy в /usr/local/bin. Также можно поставить с помощью pyenv.
PyPy работает на Mac, Linux (не все дистрибутивы) или Windows.
Для запуска кода с помощью PyPy вместо команды python3 (как c помощью CPython) достаточно воспользоваться командой pypy3:
Pyston
Pyston — это форк CPython 3.8.8 с дополнительной оптимизацией производительности. В настоящее время он поддерживает установку только из исходников. Или с помощью pyenv.
В Pyston поддерживаются все возможности CPython, в том числе C API для разработки расширений на языке Си. Среди основных отличий Pyston от CPython помимо общих оптимизаций выделяется использование DynASM JIT и inline-кэширования.
Заключение
Итак, мы рассмотрели 5 фреймворков AOT-компиляции Python. Для любителей аналитики, ниже приведена таблица со сравнительным анализом.
Как работает Python?

Всем еще раз привет, сейчас расскажу о том, как работает Python, что такое интерпретатор, как работает компилятор и что такое байт-код, далее расскажу о виртуальной машине (PVM) и о производительности Python. Также о альтернативных реализациях интерпретатора.
После того, как вы установили себе Python, перейдем к теоретически-практической части и начнем с того что из себя представляет интерпретатор.
Интерпретатор
Интерпретатор — это такая программа, которая выполняет другие программы. Когда вы пишете программу на языке Python, интерпретатор читает вашу программу и выполняет содержащиеся в ней инструкции. В действительности, интерпретатор — это слой программной логики между вашим программным кодом и аппаратурой вашего компьютера.
В зависимости от используемой версии Python сам интерпретатор может быть реализован как программа на языке C, как набор классов Java и в каком-либо другом виде, но об этом позже.
Запуск сценария в консоли
Давайте запустите в консоле интерпретатор:
Теперь он ожидает ввода комманд, введите туда следующую инструкцию:
ура, наша первая программа! 😀
Запуск сценария из файла
Создайте файл «test.py», с содержимым:
и выполните этот файл:
Вы увидите в консоли результат, поехали дальше!
Динамическая компиляция и байт-код
После того, как запустите сценарий, Python сначала компилирует исходный текст сценария в байт-код для виртуальной машины. Компиляция — это просто этап перевода, а байт-код это низкоуровневое платформонезависимое представление исходного текста программы. Python транслирует каждую инструкцию в исходном коде сценария в группы инструкций байт-кода для повышения скорости выполнения программы, так как байт-код выполняется намного быстрее. После компиляции в байт-код, создается файл с расширением «.pyc» по соседству с исходным текстом сценария.
В следующий раз, когда вы запустите свою программу интерпретатор минует этап компиляции и отдаст на выполнение откомпилированный файл с расширением «.pyc». Однако, если вы изменили исходные тексты вашей программы, то снова произойдет этап компиляции в байт-код, так как Python автоматически следит за датой изменения файла с исходным кодом.
Если Python окажется не в состоянии записать файл с байт-кодом, например из-за отсутствия прав на запись на диск, то программа не пострадает, просто байт-код будет собран в памяти и при завершении программы оттуда удален.
Виртуальная машина Python (PVM)
После того как пройдет процесс компиляции, байт-код передается механизму под названием виртуальная машина, которая и выполнит инструкции из байт-кода. Виртуальная машина — это механизм времени выполнения, она всегда присутствует в составе системы Python и это крайняя составляющая системы под названием «Интерпретатор Python».

Для закрепления пройденного еще раз проясним ситуацию, компиляция в байт-код производится автоматически, а PVM — это всего лишь часть системы Python, которую вы установили вместе с интерпретатором и компилятором. Все происходит прозрачно для программиста, и вам не надо выполнять эти операции вручную.
Производительность
Программисты имеющие опыт работы с такими языками как C и C++, могут заметить некоторые отличия в модели выполнения Python. Первое — это отсутствие этапа сборки или вызова утилиты «make», программы на Python могут быть сразу же запущены после написания исходного кода. Второе отличие — байт-код не является двоичным машинным кодом (например инструкции для микропроцессора Intel), он является внутренним представлением программы на языке Python.
По этим причинам программы на Python не могут выполняться также быстро как на C/C++. Обход инструкций выполняет виртуальная система, а не микропроцессор, и чтобы выполнить байт-код, необходима дополнительная интерпретация, инструкции которой требуют большего времени, чем машинные инструкции микропроцессора.
Однако, с другой стороны, в отличии от традиционных интерпретаторов, например как в PHP, здесь присутствует дополнительный этап компиляции — интерпретатору не требуется каждый раз анализировать исходный текст программы.
В итоге, Python по производительности находится между традиционными компилирующими и традиционными интерпретирующими языками программирования.
Альтернативные реализации Python
То что было сказано выше о компиляторе и виртуальной машине, характерно для стандартной реализации Python, так называемой CPython (реализации на ANSI C). Однако также существует альтернативные реализации, такие как Jython и IronPython, о которых пойдет сейчас речь.
CPython
Это стандартная и оригинальная реализация Python, названа так, потому что написана на ANSI C. Именно ее мы установили, когда выбрали пакет ActivePython или установили из FreeBSD портов. Поскольку это эталонная реализация, она как правило работает быстрее, устойчивее и лучше, чем альтернативные реализации.
Jython
Первоначальное название JPython, основная цель — тесная интеграция с языком программирования Java. Реализация Jython состоит из Java-классов, которые выполняют компиляцию программного кода на языке Python в байт-код Java и затем передают полученный байт-код виртуальной машине Java (JVM).
Цель Jython состоит в том, чтобы позволить программам на языке Python управлять Java-приложениями, точно также как CPython может управлять компонентами на языках C/C++. Эта реализация имеет беcшовную интеграцию с Java. Поскольку программный код на Python транслируется в байт-код Java, во время выполнения он ведет себя точно также, как настоящая программа на языке Java. Программы на Jython могут выступать в качестве апплетов и сервлетов, создавать графический интерфейс с использованием механизмов Java и т.д. Более того, Jython обеспечивает поддержку возможности импортировать и использовать Java-классы в программном коде Python.
Тем не менее, поскольку реализация Jython обеспечивает более низкую скорость выполнения и менее устойчива по сравнению с CPython, она представляет интерес скорее для разработчиков программ на языке Java, которым необходим язык сценариев в качестве интерфейса к Java-коду.
IronPython
Реализация предназначена для обеспечения интеграции программ Python с приложениями, созданными для работы в среде Microsoft .NET Framework операционной системы Windows, а также в Mono — открытом эквиваленте для Linux. Платформа .NET и среда выполнения языка C# предназначены для обеспечения взаимодействия между программными объектами — независимо от используемого языка программирования, в духе более ранней модели COM компании Microsoft.
IronPython позволяет программам на языке Python играть роль как клиентских, так и серверных компонентов, доступных из других языков программирования .NET. Поскольку разработка ведется компанией Microsoft, от IronPython, помимо прочего, можно было бы ожидать существенной оптимизации производительности.
Средства оптимизации скорости выполнения
Существуют и другие реализации, включая динамический компилятор Psyco и транслятор Shedskin C++, которые пытаются оптимизировать основную модель выполнения.
Динамический компилятор Psyco
Система Psyco — это компонент, расширяющий модель выполнения байт-кода, что позволяет программам выполняться быстрее. Psyco является расширением PVM, которое собирает и использует информацию о типах, чтобы транслировать части байт-кода программы в истинный двоичный машинный код, который выполняется гораздо быстрее. Для такой трансляции не требуется вносить изменения в исходный код или производить дополнительную компиляцию в ходе разработки.
Во время выполнения программы, Psyco собирает информацию о типах объектов, и затем эта информация используется для генерации высокоэффективного машинного кода, оптимизированного для объектов этого типа. После этого произведенный машинный код заменяет соответствующие участки байт-кода, тем самым увеличивается скорость выполнения.
В идеале некоторые участки программного кода под управление Psyco могут выполняться также быстро, как скомпилированный код на языке Си.
Psyco обеспечивает увеличение скорости от 2 до 100 раз, но обычно в 4 раза, при использовании немодифицированного интерпретатора Python. Единственный минус у Psyco, это то обстоятельство, что в настоящее время он способен генерировать машинный код только для архитектуры Intel x86.
Psyco не идет в стандартной поставке, его надо скачать и установить отдельно. Еще есть проект PyPy, который представляет собой попытку переписать PVM с целью оптимизации кода как в Psyco, проект PyPy собирается поглотить в большей мере проект Psyco.
Транслятор Shedskin C++
Shedskin — это система, которая преобразует исходный код на языке Python в исходный код на языке C++, который затем может быть скомпилирован в машинный код. Кроме того, система реализует платформонезависемый подход к выполнению программного кода Python.
Фиксированные двоичные файлы (frozen binaries)
Иногда необходимо из своих программ на Python создавать самостоятельные исполняемые файлы. Это необходимо скорее для упаковки и распространения программ.
Фиксированные двоичные файлы объединяют в единый файл пакета байт-код программ, PVM и файлы поддержки, необходимые программам. В результате получается единственный исполняемый файл, например файл с расширение «.exe» для Windows.
На сегодняшний день существует три основных инструмента создания «frozen binaries»:
- py2exe — он может создавать автономные программы для Windows, использующие библиотеки Tkinter, PMW, wxPython и PyGTK для создания графического интерфейса, программы использующие программные средства создания игр PyGame, клиентские программы win32com и многие другие;
- PyInstaller — напоминает py2exe, но также работает в Linux и UNIX и способен производить самоустанавливающиеся исполняемые файлы;
- freeze — оригинальная версия.
Вам надо загружать эти инструменты отдельно от Python, они распространяются бесплатно.
Фиксированные двоичные файлы имеют немалый размер, ибо они содержат в себе PVM, но по современным меркам из все же нельзя назвать необычно большими. Так как интерпретатор Python встроен непосредственно в фиксированные двоичные файлы, его установка не является обязательным требованием для запуска программ на принимающей стороне.
Резюме
На сегодня всё, в следующей статье расскажу о стандартных типах данные в Python, ну и в последующих статьях рассмотрим каждый тип в отдельности, а также функции и операторы для работы с этими типами.
Комментарии
создал файл, запустил его через пайтон, но пишет, что ошибка кодировки (файл сохранен в UTF-8) 🙁
SyntaxError: Non-ASCII character ‘\xd0’
Подробнее о Python — Python: Настройка окружения
Чтобы глубже погрузиться в настройку окружения Python, нам нужно вспомнить теоретические основы этого языка. Они помогут глубже разобраться в окружении и работе с ним.
Язык программирования
Что такое язык программирования? За этим понятием скрываются две связанных, но независимых темы.
С одной стороны, языком программирования называют синтаксические и семантические правила, по которым записывается и работает исходный код.
В отличие от естественных языков, эти правила достаточно строги. Любая мельчайшая ошибка приведет к тому, что код либо не запустится, либо будет работать некорректно.
Например, в Python нельзя написать my name = 5 с пробелом в имени переменной. Эти правила существуют не только в книгах, но и в головах конкретных программистов и разработчиков языка.
Часто весь свод правил существует в виде отдельного специального документа и называется спецификацией.
С другой стороны, языком программирования называют программу, которая запускает и компилирует наш код. Обычно ее называют средой выполнения.
Среда выполнения — это конкретное воплощение спецификации, поэтому ее иногда называют реализацией.
У конкретного языка может существовать несколько реализаций, в том числе эталонная реализация, на которую равняются все остальные. Различные реализации могут разрабатываться разными людьми и компаниями.
У Python нет выделенной спецификации, но есть эталонная реализация. Она называется CPython — это интерпретатор Python, реализованный на языке C. Если вы слышите разговоры про Python, то скорее всего имеется в виду именно эталонная реализация CPython.
Прочие варианты обычно имеют свои названия. Например, реализация языка для запуска программ на платформе .NET называется IronPython.
Python
Python — интерпретируемый язык программирования с сильной динамической типизацией. Разберем эти слова по отдельности.
Интерпретируемый язык программирования
Существуют языки программирования, в которых есть стадия компиляции в машинный код. Например, компиляция есть у языков C, Rust, Go. Это компилируемые языки.
Python работает по-другому. Программа исполняется интерпретатором шаг за шагом, а не запускается напрямую на процессоре компьютера. Поэтому для запуска программы на Python всегда нужна среда исполнения (интерпретатор). Только она может выполнять Python-программы.
Строго говоря, и у Python есть фаза компиляции, но при этом внешне он ведет себя именно как интерпретируемый язык программирования:
- Вы запускаете программу
- Интерпретатор открывает файлы программы и загружает из них исходный код
- Затем интерпретатор преобразует исходный код в байткод, проверяет ошибки синтаксиса и начинает исполнять по шагам
Динамическая типизация
Есть языки, в которых интерпретатор производит проверку типов, доступности функций и переменных во время выполнения кода. Такие языки называются динамически типизированными. Если мы случайно ошиблись и вызвали несуществующую функцию, то ошибка всплывет только во время вызова этой функции.
В статически типизированных языках подобные ошибки отслеживаются раньше — на этапе анализа исходного текста без запуска кода на выполнение. Слово «статический» как раз означает, что программа не выполняется.
Обычно статическими проверками занимаются компиляторы, но существуют и специальные инструменты — статические анализаторы кода. Для некоторых языков с динамической типизацией такие анализаторы тоже существуют, но отслеживают значительно меньшее число ошибок.
Сильная типизация
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно