Отладка, где метод возвращает Нет

У меня есть большой старый метод Python, содержащий около двадцати return операторов.

Метод не должен возвращать None, но он делает это. Он повторяется в простом случае.

До сих пор я использовал отладчик и прошел через строку кода, чтобы найти соответствующий оператор return.

Но есть ли более простой способ?

Есть ли способ повысить исключение, как только метод возвращает None?

и, конечно, мне нужно увидеть строку, содержащую оператор return.

Пример:

def big_method(arg1, some_var):
    #.... many returns
    if arg1:
        return some_var # <------
    #... many returns


assert not big_method(True, None) is None

Выше приведен фрагмент кода. Результат:

Traceback (most recent call last):
  File "/home/modwork_vums_d/src/manyreturns.py", line 8, in <module>
    assert not big_method(True, None) is None
AssertionError

Выше трассировка не очень помогает, так как я хочу видеть строку внутри big_method(). В приведенном выше примере я хочу видеть, что я отмечен <------.

Я использую PyCharm, но приветствуется чистый python или другое решение.

Только для записей. Существует следующий вопрос, который пытается включить эту функцию в PyCharm: PyCharm: Debugging: r (eturn) Продолжить выполнение до тех пор, пока текущая функция не вернется

Ответ 1

pdb имеет команду r(eturn) для этой необходимости:

г (eturn) Продолжайте выполнение до тех пор, пока не вернется текущая функция.

Пример:

> /Users/georgexsh/wasteland/tmp/app.py(6)<module>()
-> assert not big_method(True, None) is None
(Pdb) s
--Call--
> /Users/georgexsh/wasteland/tmp/app.py(1)big_method()
-> def big_method(arg1, some_var):
(Pdb) r
--Return--
> /Users/georgexsh/wasteland/tmp/app.py(3)big_method()->None
-> return some_var

Подробнее см. pdb doc.

Ответ 2

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

#!/usr/bin/env python
import os
import sys
import inspect
def get_head_info():
    try:
        raise Exception
    except:
        f = sys.exc_info()[2].tb_frame.f_back
    return '%s, %s' % (f.f_code.co_name, str(f.f_lineno))

def big_method(arg1, some_var):
    if arg1:
        return (print(get_head_info()), some_var)
    return (print(get_head_info()), True)
if __name__ == '__main__':
    assert not big_method(True, None)[1] is None

в python3.5 на win10, он получит

big_method, 17
Traceback (most recent call last):
  File "C:\test.py", line 21, in <module>
    assert not big_method(True, None)[1] is None
AssertionError

return (print(get_head_info()), some_var) Это точка, когда возврат был триггером, он сначала оценит оператор печати, напечатает номер строки (в этом случае 17), а затем получит значение None, наконец вы получите (None, some_var).

Ответ 3

Для меня самый простой способ - использовать декоратор, который будет проверять вывод вашей функции. Маленький пример:

def check_none_in_response(func):
    def wrapper(arg1, some_var):
        rs = func(arg1, some_var)
        assert rs is not None
        return rs

    return wrapper

Использование:

@check_none_in_response
<your method>

Надеюсь, это поможет вам.