Как я могу проверить, является ли текущий код частью блока try-кроме? - PullRequest
11 голосов
/ 17 апреля 2019

Я отлаживаю функцию, которую я написал как часть некоторой формы плагина. Похоже, что функция не выполняет то, что должна, и у меня есть подозрение, что где-то в стеке кто-то перехватывает исключения или вызывает (очень специфичное или очень общее) исключение и проверяет, что происходит (но если это проглотил, он все еще не говорит мне, где). Я мог бы войти в отладчик и проверить исходный код на каждом уровне стека. Есть ли более прямой способ перечислить любые блоки try-кроме, частью которых может быть текущий код, в частности, часть try любого такого блока?

Это, конечно, исключительно для целей отладки.

Ответы [ 2 ]

9 голосов
/ 17 апреля 2019

Это впечатляюще возможно, я что-то здесь упускаю (я только что озвучил вывод dis.dis() для функции catcher), но по крайней мере это ловит простые случаи ловли вещей на Python 3.7:

import sys
import dis


def are_we_being_caught():
    frame = sys._getframe(1)
    while frame:
        bytecode = dis.Bytecode(frame.f_code)
        except_stack = 0
        for instr in bytecode:
            if instr.opname == "SETUP_EXCEPT":  # Going into a try: except: block
                except_stack += 1
            elif instr.opname == "POP_EXCEPT":  # Exiting a try: except: block
                except_stack -= 1
            if instr.offset > frame.f_lasti:  # Past the current instruction, bail out
                break
        if except_stack:  # If we `break`ed in the middle of a SETUP/POP pair
            print(frame, "may be catching exceptions now")
        frame = frame.f_back


def catcher(fn):
    try:
        x = fn()
    except:
        x = None  # YOLO :D
    return x


def f1():
    return 8


def f2():
    are_we_being_caught()
    raise ValueError("foo")


print(catcher(f1))
print(catcher(f2))

выходы

8
<frame at 0x109d2d238, file 'so55729254.py', line 24, code catcher> may be catching exceptions now
None
1 голос
/ 17 апреля 2019

Это довольно сложно: внутренне каждый фрейм поддерживает стек блоков , но я не думаю, что есть какой-либо API для доступа к нему (не говоря уже о Python). Таким образом, вам придется пройтись по стековым фреймам, разобрать код, чтобы определить диапазон ваших блоков try (см. Коды операций SETUP_EXCEPT и SETUP_FINALLY), и посмотреть, попадает ли «текущая строка» фрейма стека в этот блок .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...