Отладка ошибок и тестирование обучения Python

искусственный интеллект Python модульный тест PyCharm

Учебный каталог Python

  1. Использование Python3 под Mac
  2. Типы данных для изучения Python
  3. Функция обучения Python
  4. Расширенные возможности обучения Python
  5. Функциональное программирование для изучения Python
  6. Модуль обучения Python
  7. Объектно-ориентированное программирование для изучения Python
  8. Расширенное объектно-ориентированное программирование для изучения Python
  9. Отладка ошибок и тестирование обучения Python
  10. Программирование ввода-вывода для изучения Python
  11. Процесс обучения Python и поток
  12. Регулярность изучения Python
  13. Общие модули для изучения Python
  14. Python обучение сетевому программированию

В процессе работы программы всегда будут возникать различные ошибки, в Python есть встроенный механизм обработки исключений, помогающий нам справляться с ошибками.

debug

обработка ошибок

В процессе работы программы, в случае возникновения ошибки, по предварительному согласованию может быть возвращен код ошибки, чтобы можно было узнать, есть ли ошибка и причину ошибки. Очень часто в вызовах, предоставляемых операционной системой, возвращаются коды ошибок. например, функция открытия файлаopen(), возвращает дескриптор файла (то есть целое число) в случае успеха и возвращает в случае ошибки-1.

Очень неудобно использовать код ошибки, чтобы указать, есть ли ошибка, потому что нормальный результат, который должна возвращать сама функция, смешивается с кодом ошибки, поэтому вызывающая сторона должна использовать много кода, чтобы судить о том, есть ли ошибка. , поэтому языки высокого уровня обычно имеют встроенный наборtry...except...finally...механизм обработки ошибок, и Python не является исключением.

try

try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
finally:
    print('finally...')
print('END')

Когда мы думаем, что какой-то код может пойти не так, мы можем использоватьtryЧтобы запустить этот код, если в выполнении есть ошибка, последующий код не будет продолжать выполняться, а сразу перейдет к коду обработки ошибок, то естьexceptблок операторов, выполненныйexceptПосле этого, если естьfinallyблок операторов, выполнитьfinallyБлок операторов в этот момент выполняется.

Ошибки Python на самом деле являются классами, и все типы ошибок унаследованы отBaseException, поэтому используяexceptСледует отметить, что он не только отлавливает ошибки этого типа, но и «отлавливает все» его подклассы.

стек вызовов

Если ошибка не обнаружена, она просто продолжает расти и перехватывается интерпретатором Python, печатает сообщение об ошибке и программа завершает работу. приди и посмотриerr.py:

# err.py:
def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    bar('0')

main()

Выполняем, результат такой:

$ python3 err.py
Traceback (most recent call last):
  File "err.py", line 11, in <module>
    main()
  File "err.py", line 9, in main
    bar('0')
  File "err.py", line 6, in bar
    return foo(s) * 2
  File "err.py", line 3, in foo
    return 10 / int(s)
ZeroDivisionError: division by zero

Мы видим всю цепочку ошибочных вызовов сверху донизу.

ошибка журнала

Если вы не поймаете ошибку, вы можете заставить интерпретатор Python распечатать стек ошибок, но программа будет завершена. Теперь, когда мы можем поймать ошибку, мы можем распечатать стек ошибок, проанализировать причину ошибки и позволить программе продолжить работу.

Встроенный PythonloggingМодули могут очень легко регистрировать сообщения об ошибках:

# err_logging.py

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)

main()
print('END')

Выполните указанный выше модуль:

$ python3 err_logging.py
ERROR:root:division by zero
Traceback (most recent call last):
  File "err_logging.py", line 13, in main
    bar('0')
  File "err_logging.py", line 9, in bar
    return foo(s) * 2
  File "err_logging.py", line 6, in foo
    return 10 / int(s)
ZeroDivisionError: division by zero
END

бросить ошибку

Поскольку ошибки — это классы, перехват ошибки — это перехват экземпляра этого класса. Так что ошибки не создаются из воздуха, а создаются и выбрасываются намеренно. Встроенные функции Python выдают множество типов ошибок, и функции, которые мы пишем сами, тоже могут выдавать ошибки.

Если вы хотите выдать ошибку, вы можете сначала определить неправильный класс в соответствии с вашими потребностями, выбрать хорошие отношения наследования, а затем использоватьraiseоператор выдает экземпляр ошибки:

# err_raise.py
class FooError(ValueError):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n

foo('0')

Execute, мы можем, наконец, отследить наши собственные определенные ошибки:

$ python3 err_raise.py 
Traceback (most recent call last):
  File "err_throw.py", line 11, in <module>
    foo('0')
  File "err_throw.py", line 8, in foo
    raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0

Наконец, давайте рассмотрим еще один способ обработки ошибок:

# err_reraise.py

def foo(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n

def bar():
    try:
        foo('0')
    except ValueError as e:
        print('ValueError!')
        raise

bar()

существуетbar()В функции мы явно поймали ошибку, но выведитеValueError!После этого снова передать ошибкуraiseЗаявление выброшено, не больно ли?

На самом деле такая обработка ошибок не только не больна, но и довольно распространена. Цель отлова ошибок — просто записать их для последующего отслеживания. Однако, поскольку текущая функция не знает, как обработать ошибку, наиболее подходящий способ — продолжать выдавать ее и позволить вызывающему объекту верхнего уровня обработать ее. Например, когда сотрудник не может справиться с проблемой, он бросает ее своему начальнику, а если босс не может с ней справиться, он продолжает ее бросать, и в конце концов она будет передана генеральному директору для решения.

raiseЕсли оператор не принимает параметров, он выдаст текущую ошибку как есть. Кроме того, вexceptсерединаraiseОшибка также может преобразовать один тип ошибки в другой:

try:
    10 / 0
except ZeroDivisionError:
    raise ValueError('input error!')

отладка

Вероятность того, что программу можно написать один раз и нормально запустить, очень мала, в основном не более 1%. Всегда будут различные ошибки, которые необходимо исправить. Некоторые ошибки очень просты, достаточно посмотреть сообщение об ошибке, а некоторые ошибки очень сложны.Нам нужно знать, какие значения переменных правильные, а какие неправильные, когда возникает ошибка.Поэтому нам нужен целый набор средств отлаживать программу, исправлять ошибки.

print()

использоватьprint()Распечатайте переменные, которые могут быть проблематичными.

утверждение

def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')

assertозначает, что выражениеn != 0должно бытьTrue, иначе по логике работы программы код позади обязательно пойдет не так.

Если утверждение не удается,assertсам оператор выдаетAssertionError.

logging

logging позволяет указать уровень ведения журнала, сdebug,info,warning,errorждем несколько уровней, когда укажемlevel=INFOчас,logging.debugпросто не работает. Точно так же укажитеlevel=WARNINGЗадний,debugиinfoпросто не работает. Таким образом, вы можете безопасно выводить различные уровни информации без удаления и, наконец, контролировать, какой уровень информации выводится.

loggingЕще одним преимуществом является то, что при простой настройке оператор может одновременно выводиться в разные места, например в консоль и в файл.

import logging
logging.basicConfig(level=logging.INFO)

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

pdb

Отладчик Python, pdb, позволяет программе работать в пошаговом режиме, и вы можете в любое время просмотреть статус выполнения. Сначала подготовим программу:

# err.py
s = '0'
n = int(s)
print(10 / n)

Затем начните:

$ python -m pdb err.py
> /Users/michael/Github/learn-python3/samples/debug/err.py(2)<module>()
-> s = '0'

с параметрами-m pdbПосле запуска pdb находит код, который будет выполняться следующим-> s = '0'. введите командуlчтобы увидеть код:

(Pdb) l
  1     # err.py
  2  -> s = '0'
  3     n = int(s)
  4     print(10 / n)

введите командуnВы можете пройти код.

pdb.set_trace()

Этот метод также использует pdb, но не требует пошагового выполнения, нам нужно толькоimport pdb, а затем, где это может пойти не так, поставитьpdb.set_trace(), вы можете установить точку останова:

# err.py
import pdb

s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)

Запустите код, программа автоматическиpdb.set_trace()Сделайте паузу и войдите в среду отладки pdb, вы можете использовать командуpПросмотрите переменные или используйте командуcПродолжать работать.

IDE

В настоящее время лучшими IDE для Python являются:

Код Visual Studio:code.visualstudio.com/, требует установки подключаемого модуля Python.

Пичарм:www.jetbrains.com/pycharm/

Кроме того,EclipseплюсpydevПлагины также могут отлаживать программы Python.

модульный тест

Модульное тестирование — это работа по тестированию модуля, функции или класса для проверки правильности.

Проверка документации

Если вы часто читаете официальную документацию по Python, то можете заметить, что во многих из них есть примеры кода.

Эти примеры кодов можно вводить и выполнять в интерактивной среде Python, а результаты согласуются с примерами кодов, показанными в документации.

Эти коды и другие инструкции могут быть записаны в комментариях, а затем автоматически сгенерированы некоторыми инструментами.

Далее: Программирование ввода-вывода для обучения Python