Сообщить об ошибке.

Улучшенный интерактивный интерпретатор в Python 3.13

В Unix-подобных системах, таких как Linux или macOS, а также Windows, Python3 теперь использует новую интерактивную оболочку. Когда пользователь запускает REPL из интерактивного терминала, интерактивная оболочка поддерживает следующие новые функции:

  • Цветные подсказки.
  • Многострочное редактирование с сохранением истории.
  • Просмотр интерактивной справки с использованием F1 с отдельной историей команд.
  • Просмотр истории с использованием F2, который пропускает выходные данные, а также подсказки >>> и ....
  • "Режим вставки" с F3, который упрощает вставку больших блоков кода (нажмите F3 еще раз, чтобы вернуться к обычному приглашению).
  • Возможность выдавать команды, специфичные для REPL, такие как help, exit, и quit без необходимости использовать круглые скобки для вызова после имени команды.

Если новая интерактивная оболочка нежелательна, то ее можно отключить с помощью переменной окружения PYTHON_BASIC_REPL. Новая оболочка для Unix-подобных систем требует установленного модуля curses.

Рекомендация: в период обучения Python3 рекомендуем установить модуль ptpython, который создан для этих целей

  • Подсветка синтаксиса.
  • Многострочное редактирование (стрелка вверх работает).
  • Автодополнение.
  • Поддержка мыши.
  • Поддержка цветовых схем.
  • Поддержка вставки в квадратных скобках.
  • Привязки клавиш Vi и Emacs.
  • … и многое другое.

Скриншот интерфейса модуля ptpython

Содержание:


Управление цветом интерпретатора Python 3.13

Интерпретатор Python3.13 по умолчанию настроен на использование цветов для выделения выходных данных в определенных ситуациях, например, при отображении трассировок. Этим поведением можно управлять, устанавливая различные переменные среды.

Установка переменной окружения TERM на dumb отключит цвет.

Если задана переменная окружения FORCE_COLOR, то цвет будет включен независимо от значения TERM . Это полезно в системах CI, которые не являются терминалами, но все равно могут отображать управляющие последовательности ANSI.

Если задана переменная окружения NO_COLOR, то Python3.13 отключит все цвета в выходных данных. Это имеет приоритет над FORCE_COLOR.

Все эти переменные окружения используются также другими инструментами для управления выводом цвета. Для управления выводом цвета только в интерпретаторе Python можно использовать переменную окружения PYTHON_COLORS. Эта переменная имеет приоритет над NO_COLOR, которая, в свою очередь, имеет приоритет над FORCE_COLOR.

Улучшенные сообщения об ошибках в интерпретаторе Python 3.13

Интерпретатор теперь раскрашивает сообщения об ошибках при отображении обратных трассировок по умолчанию. Этой функцией можно управлять с помощью новой переменной среды PYTHON_COLORS, а также канонических переменных среды NO_COLOR и FORCE_COLOR.

При возникновении ошибки интерпретатор выводит сообщение об ошибке и трассировку стека. Затем в интерактивном режиме он возвращается к основной подсказке. Когда входные данные поступают из файла, он завершает работу с ненулевым статусом завершения после печати трассировки стека. Исключения, обрабатываемые инструкцией try и предложением except, не являются ошибками в данном контексте. Некоторые ошибки являются безусловно фатальными и приводят к завершению с ненулевым статусом завершения; это относится к внутренним несоответствиям и некоторым случаям нехватки памяти. Все сообщения об ошибках записываются в стандартный поток ошибок. Обычный вывод выполняемых команд записывается в стандартный вывод.

Ввод символа прерывания (обычно Ctrl-C или Delete) в основное или дополнительное приглашение отменяет ввод и возвращает к основному приглашению. Передача прерывания во время выполнения команды вызывает исключение KeyboardInterrupt, которое может быть обработано с помощью инструкции try ... except.

Распространенной ошибкой является написание скрипта с тем же именем, что и у модуля стандартной библиотеки. Если это приводит к ошибкам, то теперь отображается более полезное сообщение об ошибке:

$ python random.py
# Traceback (most recent call last):
#   File "/home/random.py", line 1, in <module>
#     import random; print(random.randint(5))
#     ^^^^^^^^^^^^^
#   File "/home/random.py", line 1, in <module>
#     import random; print(random.randint(5))
#                         ^^^^^^^^^^^^^^
# AttributeError: module 'random' has no attribute 'randint' (consider renaming 
# '/home/random.py' since it has the same name as the standard library module 
# named 'random' and the import system gives it precedence)

Аналогично, если скрипт имеет то же имя, что и сторонний модуль, который он пытается импортировать, и это приводит к ошибкам, теперь также отображается более полезное сообщение об ошибке:

$ python numpy.py
# Traceback (most recent call last):
#   File "/home/numpy.py", line 1, in <module>
#     import numpy as np; np.array([1,2,3])
#     ^^^^^^^^^^^^^^^^^^
#   File "/home/numpy.py", line 1, in <module>
#     import numpy as np; np.array([1,2,3])
#                         ^^^^^^^^
# AttributeError: module 'numpy' has no attribute 'array' 
# (consider renaming '/home/numpy.py' if it has the same 
# name as a third-party module you intended to import)

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

>>> "better error messages!".split(max_split=1)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#     "better error messages!".split(max_split=1)
#     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
# TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?

Классы имеют новый атрибут __static_attributes__, заполняемый компилятором кортежем имен атрибутов этого класса, доступ к которым осуществляется через self.X из любой функции в его теле.

Исполняемые скрипты Python3

В системах Unix скрипты Python можно сделать исполняемыми напрямую, подобно скриптам оболочки bash, поместив строку #!/usr/bin/env python3 в начале скрипта, при условии, что путь к интерпретатору находится в пользовательском PATH. #! должны быть первыми двумя символами файла. На некоторых платформах эта первая строка должна заканчиваться переводом строки в стиле Unix ('\n'), а не Windows ('\r\n'). Обратите внимание, что символ хеша, '#', используется для начала комментария в Python.

Скрипту можно присвоить исполняемый режим или разрешение, используя команду bash chmod: $ chmod + x myscript.py.

В системах Windows нет понятия "исполняемый режим". Программа установки Python автоматически связывает расширение файлов .py с python.exe, так что двойной щелчок по файлу Python запускает его как скрипт. Расширение также может быть .pyw, в этом случае окно консоли, которое обычно появляется, будет отключено.

Интерактивный загрузочный файл

При интерактивном использовании Python часто бывает удобно выполнять некоторые стандартные команды при каждом запуске интерпретатора. Это можно сделать, установив переменную окружения с именем PYTHONSTARTUP в качестве имени файла, содержащего команды запуска. Это похоже на функцию .profile оболочек Unix.

Этот файл читается только в интерактивных сеансах, не тогда, когда Python считывает команды из скрипта, и не тогда, когда /dev/tty указан в качестве явного источника команд (который в противном случае ведет себя как интерактивный сеанс). Он выполняется в том же пространстве имен, где выполняются интерактивные команды, так что объекты, которые он определяет или импортирует, могут использоваться без каких-либо оговорок. Также, в этом файле можно изменить подсказки sys.ps1 и sys.ps2.

>>> import sys
>>> sys.ps1
# '>>> '
>>> sys.ps2
# '... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
# Yuck!
C>

Если необходимо прочитать дополнительный стартовый файл из текущего каталога, то можно запрограммировать это в глобальном стартовом файле, используя код типа if os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read()). Если нужно использовать загрузочный файл в скрипте, то должны сделать это явно в скрипте:

import os
filename = os.environ.get('PYTHONSTARTUP')
if filename и os.path.isfile(filename):
    with open(filename) as fobj:
        startup_file =  fobj.read()
    exec(startup_file)

Модули настройки

Python предоставляет два хука, позволяющих его настраивать: sitecustomize и usercustomize. Чтобы посмотреть, как это работает, нужно сначала найти расположение пользовательских пакетов site-packages. Запустите Python3 и выполните этот код:

>>> import site
>>> site.getusersitepackages()
# '/home/user/.local/lib/python3.x/site-packages'

Теперь, в этом каталоге можно создать файл с именем usercustomize.py и поместить в него все, что захотите. Это повлияет на каждый вызов Python, если только он не запускается с опцией -s, которая отключает автоматический импорт.

sitecustomize работает таким же образом, но обычно создается администратором компьютера в глобальном каталоге пакетов сайта и импортируется перед usercustomize. Смотрите документацию к site модулю для получения более подробной информации.

Пробуем любую новую/старую версию Python3 без компиляции исходников и установки в виртуальное окружение

Попробовать улучшенный интерпретатор в Python 3.13 (любую новую/старую версию Python3) без компиляции исходников и установки в виртуальное окружение можно используя технологию Docker. Контейнеризация приложений при помощи Docker в настоящее время стала золотым стандартом портируемости/переносимости программного обеспечения. (Да, мы знаем, что правительство США на пару недель блокировало доступ из РФ к https://hub.docker.com, но компания Docker отстояла право быть открытой)

Практически все выпуски Python3 хранятся на странице "Официальные образы Python3" https://hub.docker.com/_/python.

Почему официальные образы?

Официальные образы Python3 Docker - это тщательно подобранный набор репозиториев Docker с открытым исходным кодом (вот из за этих слов был разблокирован Docker) и готовых решений. Эти образы имеют четкую документацию, пропагандируют лучшие практики и предназначены для наиболее распространенных случаев использования.

Тенденция создания многих официальных образов из исходного кода является прямым результатом попыток внимательно следовать официальным рекомендациям каждого вышестоящего разработчика относительно того, как развертывать и использовать их продукт/проект.

Для того, чтобы запустить контейнер с Python3 из образа Docker необходимо его установить. Самым простым способом установки Docker на OS Linux служит система развёртывания и управления пакетами snap, разработанная Canonical для Ubuntu. Всё это работает на широком спектре дистрибутивов Linux и позволяет создавать дистрибутивно-независимые программы.

# ставим Docker на Desktop
$ sudo snap install docker

После установки, идем на страницу https://hub.docker.com/_/python/tags и выбираем нужный образ (например, напишем в поле "Filter tags" 3.13), пусть это будет "3.13-rc-slim". Справа от тега есть команда, которой можно загрузить выбранный образ на локальный компьютер.

# загрузка официального образа Python 3.13 
# на локальный компьютер
$ sudo docker pull python:3.13-rc-slim

Осталось только запустить контейнер с Python 3.13 и попробовать новый цветной интерактивный интерпретатор.

# запуск Python 3.13 в интерактивном режиме
$ sudo docker run -it --rm python:3.13-rc-slim
# Python 3.13.0b2 (main, Jul  2 2024, 03:33:35) [GCC 12.2.0] on linux
# Type "help", "copyright", "credits" or "license" for more information.
# >>> import os
# >>> os.process_cpu_count()
# 2

где следующие параметры означают:

  • -it запускать контейнер в интерактивном режиме
  • --rm удалить контейнер после завершения интерактивного режима

Или по быстренькому запустить скрипт в Python 3.13.

Для примера, возьмем следующий скрипт python3:

# test.py
import sys

print('sys.path=', sys.path, end='\n\n')
print('###########')
print('sys.copyright =>', sys.copyright, end='\n\n')
print('###########')
print('sys.version =>', sys.version, end='\n\n')
print('###########')
print('sys.api_version =>', sys.api_version, end='\n\n')
print('###########')
print('sys.version_info =>', sys.version_info, end='\n\n')
print('###########')
print('sys.implementation =>', sys.implementation, end='\n\n')

и запустим его в окружении docker-python:

# запуск скрипта в Python 3.13
$ sudo docker run -v /path/to/script:/root -w /root --rm python:3.13-rc-slim python3 test.py

где следующие параметры означают:

  • -v /path/to/script:/root - монтирует директорию /path/to/script (папку, где лежит скрипт test.py) в папку /root запускаемого контейнера. Путь должен быть абсолютным...
  • -w /root - устанавливает папку /root в качестве рабочего каталога.
  • --rm - удаляет контейнер после завершения работы скрипта

Внимание! Вызываемый скрипт запустится от имени пользователя root, но при этом не сможет выйти за пределы или переместиться выше примонтированной к контейнеру папки /path/to/script. Другими словами, папка /path/to/script выполняет роль своеобразной песочницы для выполняемого скрипта python. Так что такой запуск вполне беопасен для ОС.

Вывод работы скрипта:

$ sudo docker run -v /home/to/script:/root -w /root --rm python:3.13-rc-slim python3 test.py 
# sys.path= ['/root', '/usr/local/lib/python313.zip', '/usr/local/lib/python3.13', '/usr/local/lib/python3.13/lib-dynload', '/usr/local/lib/python3.13/site-packages']
# 
# ###########
# sys.copyright => Copyright (c) 2001-2024 Python Software Foundation.
# All Rights Reserved.
# 
# Copyright (c) 2000 BeOpen.com.
# All Rights Reserved.
# 
# Copyright (c) 1995-2001 Corporation for National Research Initiatives.
# All Rights Reserved.
# 
# Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
# All Rights Reserved.
# 
# ###########
# sys.version => 3.13.0b2 (main, Jul  2 2024, 03:33:35) [GCC 12.2.0]
# 
# ###########
# sys.api_version => 1013
# 
# ###########
# sys.version_info => sys.version_info(major=3, minor=13, micro=0, releaselevel='beta', serial=2)
# 
# ###########
# sys.implementation => namespace(name='cpython', cache_tag='cpython-313', version=sys.version_info(major=3, minor=13, micro=0, releaselevel='beta', serial=2), hexversion=51183794, _multiarch='x86_64-linux-gnu')