Динамическая генерация кода для обработки Exception (метапрограммирование)
Подбирая варианты решений к этому вопросу, хотела использовать модуль pdb
.
С помощью модуля pdb
можно изменять переменные и выполнять функции,
вводя в консоль соответствующие команды.
Но не могу понять как можно программно отправлять команды в консоль отладки.
Перехват с помощью sys.stdout приводит к конфликту с консолью отладки pdb
.
(пробовала перехваченный out добавлять в асинхронную очередь и обрабатывать в другом потоке, но пока не получилось.)
Сейчас пробую через менеджер контекста.
Вот код:
import re
import sys
import pdb
import traceback
from contextlib import contextmanager
from rich import print, inspect
# Динамическое создание функций
def create_function(name):
def func(param):
print(f'{param}("{name}")')
return func
# Класс для перехвата вывода
class StreamInterceptor:
def __init__(self):
self.original_stdout = sys.stdout
def write(self, message):
# Перехватываем вывод и обрабатываем его
print(f"Перехваченный вывод: {message.strip()}")
def flush(self):
pass # Нужно для совместимости
def __enter__(self):
sys.stdout = self
return self
def __exit__(self, exc_type, exc_value, traceback):
sys.stdout = self.original_stdout
# Обработчик исключений
def my_except_hook(exctype, value, tb):
if exctype is not SystemExit:
tb_str = ''.join(traceback.format_exception(exctype, value, tb))
print(f"Обрабатываем исключение:\n{tb_str}")
# Извлечение имени функции из traceback
func_name = value.name
globals()[func_name] = create_function(func_name)
print(f'Создана функция: {func_name}')
inspect(globals()[func_name])
# Установка обработчика исключений
sys.excepthook = my_except_hook
# Используем контекстный менеджер для перехвата вывода
with StreamInterceptor():
# Устанавливаем точку останова перед вызовом функции
# pdb.set_trace()
Hello_world("print")
Hello_world("print")
It_is_not_print("print")
Функция my_except_hook
отрабатывает без ошибок, динамически создается функция Hello_world
и в консоль выводится строка: print("Hello_world")
.
В коде выше строчка: pdb.set_trace()
пока закомментирована, но использование pdb
необходимо, так как исключение даже обработанное приводит к закрытию контекстного менеджера.
см. output:
Обрабатываем исключение:
Traceback (most recent call last):
File "c:\KWORK\not_print.py", line 73, in <module>
Hello_world("print")
^^^^^^^^^^^
NameError: name 'Hello_world' is not defined
Создана функция: Hello_world
╭─ <function create_function.<locals>.func at 0x00000162AFEC9120> ─╮
│ def create_function.<locals>.func(param): │
│ │
│ 38 attribute(s) not shown. Run inspect(inspect) for options. │
╰──────────────────────────────────────────────────────────────────╯
print("Hello_world")
Надо чтоб код продолжил выполнение, т.е. lines: 72, 73, 74
должны выполнятся,
именно для этого и нужна breakpoint()
.
Информации по затронутым темам в сети существенно меньше, чем по Django (например).
Вопрос:
1. Как можно используя модуль pdb
, команды вводить программно, а не в консоль (ручками)?
Как реализовать протекцию всего кода?
Например при метапрограммировании, чтоб не приходилось оборачивать вtry
-except
каждую строчку, и не расставлять в таких местах запись вf.log
!?
P.S. Глобальная протекция ошибок может решить и такой вопрос.
Ответы (1 шт):
Я поняла, как можно "из кода" выполнять команды pdb
— файл .pdbrc,
но это вряд ли может быть глобальной протекцией кода.
А ещё я нашла этот вопрос и ответ на него,
если кто-нибудь задастся целью и даже реализует это —
то практической пользы в этом не будет,
т.к. в сумме эти манипуляции будут очень затратными.