Spec-Zone.ru › Python 3.11

Режим разработки Python

Новая версия 3.7.

Режим разработки Python добавляет дополнительные проверки во время выполнения, которые слишком затратны, чтобы их включать по умолчанию. Он не должен быть более подробным, чем по умолчанию, если код корректен; новые предупреждения выводятся только при обнаружении проблемы.

Его можно включить, используя опцию командной строки -X dev или задав переменную окружения PYTHONDEVMODE со значением 1.

См. также Отладочная сборка Python.

Воздействие режима разработки Python

Включение режима разработки Python аналогично следующей команде, но с дополнительными эффектами, описанными ниже:

PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3 -W default -X faulthandler

Воздействие режима разработки Python:

  • Добавить default фильтр предупреждений. Будут отображаться следующие предупреждения:

    • DeprecationWarning
    • ImportWarning
    • PendingDeprecationWarning
    • ResourceWarning

    Обычно вышеперечисленные предупреждения отфильтровываются стандартными фильтрами предупреждений.

    Ведёт себя так, как если бы использовалась опция командной строки -W default.

    Используйте опцию командной строки -W error или задайте переменную окружения PYTHONWARNINGS со значением error для обработки предупреждений как ошибок.

  • Установка отладочных обработчиков на выделения памяти для проверки:

    • Недопустимое уменьшение буфера
    • Недопустимое увеличение буфера
    • Нарушение API выделения памяти
    • Небезопасное использование GIL

    См. функцию C PyMem_SetupDebugHooks().

    Ведёт себя так, как если бы переменная окружения PYTHONMALLOC была установлена на debug.

    Чтобы включить режим разработки Python без установки отладочных обработчиков на выделения памяти, задайте переменную окружения PYTHONMALLOC со значением default.

  • Вызов faulthandler.enable() при запуске Python для установки обработчиков для сигналов SIGSEGV, SIGFPE, SIGABRT, SIGBUS и SIGILL для вывода трассировки Python при сбое.

    Ведёт себя так, как если бы использовалась опция командной строки -X faulthandler или если переменная окружения PYTHONFAULTHANDLER была установлена на 1.

  • Включение режима отладки режима отладки asyncio. Например, asyncio проверяет сопрограммы, которые не были ожидаемы, и регистрирует их.

    Ведёт себя так, как если бы переменная окружения PYTHONASYNCIODEBUG была установлена на 1.

  • Проверка аргументов encoding и errors для кодирования и декодирования строк. Примеры: open(), str.encode() и bytes.decode().

    По умолчанию, для лучшей производительности, аргумент errors проверяется только при первой ошибке кодирования/декодирования, а аргумент encoding иногда игнорируется для пустых строк.

  • Деструктор io.IOBase регистрирует исключения close().
  • Установка атрибута dev_mode объекта sys.flags на True.

Режим разработки Python по умолчанию не включает модуль tracemalloc, потому что накладные расходы (на производительность и память) были бы слишком велики. Включение модуля tracemalloc предоставляет дополнительную информацию об источнике некоторых ошибок. Например, ResourceWarning регистрирует трассировку, где был выделен ресурс, а ошибка переполнения буфера регистрирует трассировку, где был выделен блок памяти.

Режим разработки Python не предотвращает удаление опцией командной строки -O инструкций assert или установку значения __debug__ на False.

Режим разработки Python можно включить только при запуске Python. Его значение можно прочитать из sys.flags.dev_mode.

Изменено в версии 3.8: Деструктор io.IOBase теперь регистрирует исключения close().

Изменено в версии 3.9: Теперь аргументы encoding и errors проверяются для операций кодирования и декодирования строк.

Пример ResourceWarning

Пример скрипта подсчёта количества строк текстового файла, указанного в командной строке:

import sys

def main():
    fp = open(sys.argv[1])
    nlines = len(fp.readlines())
    print(nlines)
    # The file is closed implicitly

if __name__ == "__main__":
    main()

Скрипт не закрывает файл явно. По умолчанию Python не выводит никаких предупреждений. Пример с использованием README.txt, который содержит 269 строк:

$ python3 script.py README.txt
269

При включении режима разработки Python отображается предупреждение ResourceWarning:

$ python3 -X dev script.py README.txt
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback

Кроме того, включение tracemalloc показывает строку, где был открыт файл:

$ python3 -X dev -X tracemalloc=5 script.py README.rst
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
  main()
Object allocated at (most recent call last):
  File "script.py", lineno 10
    main()
  File "script.py", lineno 4
    fp = open(sys.argv[1])

Решение — явно закрыть файл. Пример с использованием контекстного менеджера:

def main():
    # Close the file explicitly when exiting the with block
    with open(sys.argv[1]) as fp:
        nlines = len(fp.readlines())
    print(nlines)

Неявное закрытие ресурса может оставлять ресурс открытым гораздо дольше, чем ожидается; это может привести к серьёзным проблемам при выходе из Python. Это плохо в CPython, но ещё хуже в PyPy. Явное закрытие ресурсов делает приложение более детерминированным и надёжным.

Пример ошибки «Bad file descriptor»

Скрипт, отображающий первую строку самого себя:

import os

def main():
    fp = open(__file__)
    firstline = fp.readline()
    print(firstline.rstrip())
    os.close(fp.fileno())
    # The file is closed implicitly

main()

По умолчанию Python не выводит никаких предупреждений:

$ python3 script.py
import os

Режим разработки Python показывает предупреждение ResourceWarning и регистрирует ошибку «Bad file descriptor» при финализации объекта файла:

$ python3 -X dev script.py
import os
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
  main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
Exception ignored in: <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
Traceback (most recent call last):
  File "script.py", line 10, in <module>
    main()
OSError: [Errno 9] Bad file descriptor

os.close(fp.fileno()) закрывает дескриптор файла. Когда финализатор объекта файла пытается снова закрыть дескриптор файла, это приводит к ошибке Bad file descriptor. Дескриптор файла должен быть закрыт только один раз. В худшем случае двойное закрытие может привести к сбою (см. bpo-18748 для примера).

Решение — удалить строку os.close(fp.fileno()) или открыть файл с closefd=False.

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/devmode.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API