Spec-Zone.ru › Python 3.12

Режим разработки 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 проверяет наличие корутин, для которых не был вызван await, и записывает информацию о них в журнал.

    Это работает так, как если бы переменная среды 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 — ещё хуже. Явное закрытие ресурсов делает приложение более предсказуемым и надёжным.

Пример ошибки «неверный файловый дескриптор»

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

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