Режим разработки 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. -
Вызывает
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