Дополнение к ответу на вопрос: Почему эту технологию (модификацию байткода) нельзя было использовать в предыдущих версиях Python? Можно ведь получить доступ к объектам кода, используя import hooks, и изменить их без использования frame evaluation API? Это невозможно сделать по нескольким причинам: 1. Readonly атрибут Нельзя модифицировать код у объекта фрейма во время выполнения этого фрейма, потому что после того, как фрейм был создан (внутри функции вычисления фреймов), его атрибут f_code является readonly, и присвоить ему новое значение не удастся. Значит, изменять код нужно будет для каждого типа объектов отдельно: для модулей, для функций и т.д. 2. Top-level Допустим, брейкпоинт находится на вернем уровне модуля, и с помощью import hooks мы получили объект модуля в рантайме. Проблема в том, что доступ к объекту кода есть только у callable объектов, он хранится в атрибуте __code__. По объекту модуля не получить объект кода, соостветсвующий этому модулю (по крайней мере, я не знаю, как это можно сделать), а значит, и заменить его модифицированной версией тоже не удастся. 3. Inner functions Даже если брейкпоинт находится внутри функции, с помощью import hooks мы сможем получить только объект модуля, который импортируется, и его атрибуты (top-level переменные, функции, классы, методы в этих классах). Однако, если в модуле есть внутренняя функция (определённая внутри другой функции), то к ней мы сможем получить доступ только при вызове внешней функции. А значит, в процессе import hooks, мы не сможем добавить в неё брейкпоинт. 4. `co_extra` field Поле `co_extra`, которое мы используем для кэширования функций с брейкпоинтами, было добавлено в объекты фреймов только в Python 3.6. Как было показано во время доклада, без него при большом количестве повторных вызовов функций, каждый раз приходится осуществлять дополнительные проверки и вызовы вспомогательных функций, что практически не улучшает производительность. 5. Import hooks Часто введение import hooks накладывает проблемы на работу некоторых фреймворков, которые также используют их довольно часто. Сейчас в PyCharm мы уже используем import hooks для поддержки отладки в PyQt Threads. И у нас есть возможность их отключения (опция "PyQt compatible" debugging), если это приводит к ошибкам при отладке пользовательской программы. То есть они не являются универсальным инструментом и имеют свои ограничения. Из перечисленных пунктов видно, что в предыдущих версиях Python реализацию брейкпоинтов на основе изменений объектов кода можно было бы осуществить только внутри функций, определённых на верхнем уровне модуля, или у методов класса. Они покрывают лишь небольшое количество примеров использования брейкпоинтов, дают сомнительное улучшение производительности (если у пользователя есть хотя бы один брейкпоинт, не попадающий под эти случаи, надо использовать старую функцию трассировки), и делают дебаггер гораздо менее стабильным (из-за использования import hooks). Возможно, при попытки реализации найдутся дополнительные ограничения для использования этого метода с предыдущими версиями Python. Спасибо большое за интересный вопрос!
@user-qw7qh5tz2t4 жыл бұрын
хз я всегда использую логирование. Вроде и так норм.