Spec-Zone.ru › Python 3.13

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

Добавлен в версии 3.7.

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

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

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

Эффекты режима разработки Python

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

PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python -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 строк:

$ python script.py README.txt
269

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

$ python -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 показывает строку, где файл был открыт:

$ python -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 не выводит никаких предупреждений:

$ python script.py
import os

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

$ python -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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/devmode.html

Spec-Zone.ru

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