Режим разработки Python
Добавлено в версии 3.7.
Режим разработки Python добавляет дополнительные проверки во время выполнения, которые слишком затратны, чтобы включать их по умолчанию. Если код корректен, он не должен быть многословнее обычного режима; новые предупреждения выводятся только при обнаружении проблемы.
Его можно включить с помощью параметра командной строки -X dev или установив переменную окружения PYTHONDEVMODE в значение 1.
См. также Отладочную сборку Python.
Эффекты режима разработки Python
Включение режима разработки Python аналогично следующей команде, но имеет дополнительные эффекты, описанные ниже:
PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python -W default -X faulthandler
Эффекты режима разработки Python:
-
Добавляет
defaultфильтр предупреждений. Выводятся следующие предупреждения:Обычно перечисленные выше предупреждения отфильтровываются стандартными фильтрами предупреждений.
Поведение такое же, как при использовании параметра командной строки
-W default.Используйте параметр командной строки
-W errorили установите переменную окруженияPYTHONWARNINGSв значениеerror, чтобы считать предупреждения ошибками. -
Устанавливает отладочные перехватчики для распределителей памяти, чтобы обнаруживать:
- Чтение за пределами буфера
- Запись за пределами буфера
- Нарушение правил использования API распределителя памяти
- Небезопасное использование GIL
См. функцию C
PyMem_SetupDebugHooks().Поведение такое же, как если бы переменная окружения
PYTHONMALLOCбыла установлена в значениеdebug.Чтобы включить режим разработки Python без установки отладочных перехватчиков для распределителей памяти, установите переменную окружения
PYTHONMALLOCв значениеdefault. -
При запуске Python вызывает
faulthandler.enable(), чтобы установить обработчики сигналов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 — еще хуже. Явное закрытие ресурсов делает приложение более предсказуемым и надежным.
Пример ошибки «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–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/devmode.html