[Все в порядке, вы можете изучить его] Исключения и решения, с которыми вы столкнетесь при изучении работы Python

Когда наши компьютерные программы работают, иногда возникают ошибки из-за различных неконтролируемых причин. Например: не удается найти нужный файл, сетевые ошибки, неверный ввод пользователя и т.д. В это время компьютерная программа не сможет продолжить работу или даже выйти напрямую. Например: Наше обычное мобильное приложение дает сбой, на веб-сайте возникает ошибка 500 или следующая ошибка в Windows:
вставьте сюда описание изображения
Я полагаю, что все будут очень раздражены, столкнувшись с такой ситуацией? Для программ, написанных на Python. Когда Python обнаруживает ошибку, интерпретатор не может продолжать выполнение, но появляются некоторые подсказки об ошибках — так называемое «исключение Python». Поэтому, чтобы наша программа работала стабильно долгое время, нужно уметь правильно обрабатывать исключения.

Ваши три ссылки (лайки, избранное, комментарии) являются движущей силой для моей непрерывной работы, спасибо.
Учитесь с интересом, преимущества за гранью воображения, интересный исходный код и опыт обучения, пакет установки инструмента, добро пожаловать в мой WeChat: bobin1124, чтобы общаться , учиться и делиться вместе.

1. Введение в исключения Python

1. Исключения в программах Python

Как уже говорилось ранее, что такое исключение Python? Не волнуйтесь, давайте посмотрим, как представлены исключения в программах Python.

вставьте сюда описание изображения

Как показано на рисунке выше, когда мы хотим запустить файл программы python test.py, после ввода в терминале и нажатия Enter после python test.py« » на экране -----test--1---появится строка информации :

Traceback (most recent call last):

  File "C:/workspace/boxuegu/exception/test.py", line 2, in <module>

    open('123.txt','r')

FileNotFoundError: [Errno 2] No such file or directory: '123.txt'

Это сообщение об исключении Python. Исключение на картинке означает, что во второй строке файла test.py произошла ошибка, которая является 输入输出型ошибкой с номером 2 " ", а 123.txtфайл с именем " " не существует.

Почему такое исключение? Давайте посмотрим, как выглядит исходный код файла программы python с именем test.py:

print('-----test--1---')

open('123.txt','r')

print('-----test--2---')

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

Это связано с тем, что мы используем функцию open(), чтобы попытаться открыть несуществующий файл " " 123.txt. Когда 123.txtфайл " " не может быть найден, программа выдаст нам FileNotFoundErrorошибку типа Нет такого файла или каталога: 123 .txt" (такого файла или каталога, как 123.txt, нет).

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

2. Общие исключения и структуры наследования

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

вставьте сюда описание изображения

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

вставьте сюда описание изображения

Полные встроенные исключения Python 3 можно найти на официальном сайте Python: https://docs.python.org/3/tutorial/errors.html.

В Python все исключения и ошибки наследуются от базового класса BaseException. Но в реальной разработке мы больше будем иметь дело с родительским классом Exception. Exception наследуется от BaseException и реализует общие методы, необходимые для обработки исключений. Встроенные исключения Python также в основном наследуются от Exception и используют собственные описания исключений в качестве имен.Правила именования часто бывают AbcException или XyzError.

вставьте сюда описание изображения

2. Обработка исключений

1. Поймать исключение

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

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

вставьте сюда описание изображения
Взгляните на следующий пример кода:

try:

    print('-----test--1---')

    open('123.txt','r')

    print('-----test--2---')

except IOError:

    pass

Видно, что второй абзац " -----test--2---" тоже не распечатывается, но программа завершается нормально. Это связано с тем, что здесь мы используем try и exclude для захвата исключения IOError и добавления метода обработки. Поэтому оператор print('-----test–2—') не выполняется.

Мы используем ключевое слово try для хранения логических кодов, указывающих, что здесь могут возникать исключения, которые необходимо обрабатывать. Если возникает исключение, когда программа выполняется для определенного оператора, она не будет продолжать выполняться, а будет немедленно искать оператор исключения, следующий за попыткой, и вводить код, включенный в исключение, для выполнения. Это отлов исключений.

Проход в ключевом слове кроме означает, что хотя исключение будет перехвачено, ничего не будет сделано; если проход будет изменен на оператор печати, то будет выведена другая информация. Другими словами, здесь также может быть выполнена другая необходимая нам логика, например, общая логика обработки исключений, например отключение, закрытие файлов, освобождение ресурсов и запись журналов. Это обработка исключений Python.

Подводя итог, try...catch... используется следующим образом:

  1. Поместите код, который может иметь проблемы, в try
  2. Поместите код обработки исключений в за исключением, когда возникает исключение, система прервет последующее выполнение кода и введет код в за исключением.

2.except фиксирует несколько исключений

Прежде всего, мы знаем, что в соответствии с типом исключения, переданным в exclude, мы можем указать захват и обработку определенного типа исключения следующим образом.

try:
    print(num)

except IOError:

    print('产生错误了')

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

Результат выглядит следующим образом:

вставьте сюда описание изображения

Ответ таков: тип ошибки, перехваченной с помощью исключения, — IOError, а исключение, сгенерированное программой в это время, — NameError, поэтому исключение не действует.

Поэтому мы немного модифицируем код следующим образом:

try:
   print(num)

except NameError:

    print('产生错误了')

Результат после повторного запуска:

вставьте сюда описание изображения
Видно, что после изменения IOError на NameError вы можете успешно ввести оператор exclude для перехвата исключения. Из этого мы знаем, что после того, как за исключением нужно будет соответствовать правильному типу исключения, оно введет соответствующий код обработки ошибок.

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

#coding=utf-8
try:

    print('-----test--1---')

    open('123.txt','r') # 如果 123.txt 文件不存在,那么会产生 IOError 异常

    print('-----test--2---')

    print(num)# 如果 num 变量没有定义,那么会产生 NameError 异常

 

except (IOError,NameError):


    #如果想通过一次 except 捕获到多个异常可以用一个元组的方式

Видно, что при перехвате нескольких исключений вы можете поместить имя типа перехватываемого исключения после исключения и передать его в кортеже. Таким образом, будь то IOError или NameError, он войдет в блок кода исключения.

3. Получите информационное описание исключения

Кроме прерывания программы, как еще с этим можно справиться? Наиболее распространенным является: распечатать или зарегистрировать аномальную информацию, чтобы мы могли просмотреть аномальное содержимое позже, выведя результаты.
Как мы упоминали ранее, исключения в Python определяются классами, поэтому нам нужно получить экземпляр класса исключения, чтобы получить доступ к информации об исключении. Помните: с помощью ключевого слова as мы можем использовать экземпляр объекта исключения в операторе exclude следующим образом:

try:
   print(a)

except NameError as result:

    print(result)

В приведенном выше примере результатом является созданный объект NameError, мы можем напечатать его непосредственно в блоке кода исключения, и программа выведет описание ошибки. Это то же самое, что вывод ошибки системы, когда мы пишем собственный код и сталкиваемся с ошибкой.

Аналогичный подход можно использовать и для нескольких исключений:

try:
  open('a.txt')

except (NameError, IOError) as result:

    print("哎呀,捕获到了异常")

    print("异常的基本信息是: ", result)

Результат операции следующий:

вставьте сюда описание изображения

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

4. Обрабатывайте разные исключения отдельно

Как выполнить различную логическую обработку для разных типов исключений? Очень просто, использование exclude очень похоже на использование ключевого слова логического суждения if. Мы можем использовать несколько исключений для обработки различных исключений и вводить различную логику последующего кода в соответствии с типом переданного исключения, как следует:

try:
 print(num)

except NameError:

    print('产生了命名错误')

except IOError:

    print('产生了文件 IO 错误')

except:

    print('出现了其他异常')

В приведенном выше коде, когда в программе, содержащейся в try, возникает ошибка NameError, она войдет в первое исключение и выведет «произошла ошибка именования», а когда в программе в попытке произойдет ошибка IOError, она войдет во второе исключение. В одном кроме вывода «Произошла ошибка ввода-вывода файла». И если есть другие исключения, отличные от двух вышеуказанных исключений, оно войдет в последнее исключение.

Обратите внимание: здесь не указывается тип исключения. Следовательно, мы можем использовать exclude для обработки различных типов ошибок исключений по-разному. Разве это не похоже на несколько условий в операторе if?

5. Используйте else для обработки нестандартных ситуаций

Подобно использованию if...else..., мы также можем использовать else для сопоставления с исключением! Когда исключения не возникает, код после ввода else продолжает выполняться.

try:
 num = 100

    print(num)

except NameError as result:

    print("捕获到了异常, 信息是: ", result)

else:

    print("程序正常运行,没有异常。")

Обратите внимание: else относится к логике, которая вводится, когда нет исключения, а не к логике, которую вводит код, когда исключение не перехвачено.

Следовательно, если в приведенном выше коде в программе возникнут другие типы исключений, кроме NameError, и они не будут перехвачены, то ни оператор exclude, ни оператор else не будут выполнены, и программа завершится из-за исключения.

Примечание: Python отличается от других языков тем, что он считает, что использование try...except...else может более четко описать поток управления логикой, в то время как другие языки, такие как Java, не имеют ключевого слова else управления потоком.

6.попробуй… наконец…

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

Давайте посмотрим на следующий пример:

import time

try:

    f = open('test.txt')

    try:

        while True:

            content = f.readline()

            if len(content) == 0:

                break

            time.sleep(2)

            print(content)

    except:

        #如果在读取文件的过程中,产生了异常,那么就会捕获到

        #比如 按下了 ctrl+c

        pass

    finally:

        f.close()

        print('关闭文件')

except:

    print("没有这个文件")

Печатается каждая строка данных в файле test.txt, и мы намеренно используем метод time.sleep для паузы в 2 секунды перед печатью каждой строки. Это делается для того, чтобы программа работала медленнее. Во время выполнения программы нажмите, чтобы Ctrl+cпрервать (отменить) программу.

Таким образом, мы можем наблюдать, как срабатывает исключение KeyboardInterrupt и программа завершает работу. Но перед выходом из программы предложение finally все еще выполняется, закрывая файл. Это гарантирует, что независимо от того, работает ли программа правильно, она не будет блокировать некоторые общедоступные ресурсы, такие как файлы, сети, память и т. д., что повышает стабильность системы и строгость логики кода.

7. Резюме

Мы знаем, что захват и обработка исключений в основном состоят из try/except/else/finally. Пожалуйста, обратите внимание на следующие примеры кода:

try:
     # 正常的代码逻辑

except A:

     # Exception A 的处理逻辑

except B:

     # Exception B 的处理逻辑

except:

     # 其他异常的处理逻辑

else:

     # 如果没发生异常,执行这里

finally:

     # 无论是否发生异常,最后执行这里

#    

Обработка исключений в Python кажется сложной, но на самом деле просто запомните приведенные выше сводные правила.

Вопрос: Какая из следующих комбинаций является неправильным соответствием?

А. попробуй… кроме…

Неправильный ответ: try...except... это самый простой метод захвата и обработки исключений.

Б. попробуй… еще…

Правильный ответ: else должен следовать за исключением, так что это неправильное использование

C. попробуй… кроме… наконец…

Неправильный ответ: добавление finally к try...except... может гарантировать, что код finally будет выполнен независимо от возникновения исключения.

Д. попробуй... наконец...

Неправильный ответ: Неиспользование, за исключением, означает, что исключения не обрабатываются, но код в finally все равно будет выполняться, а исключения будут выбрасываться вверх.

вставьте сюда описание изображения

3. Передача исключений

На втором уровне мы научились использовать try для перехвата исключений, а также научились использовать exclude и другие методы для обработки исключений. Иногда наш код может быть инкапсулирован в тело функции, которое вызывается другими функциями и т. д., что создает многоуровневый стек вызовов функций. В это время может показаться, что внутренней функции недостаточно информации для корректной обработки исключения.

Это связано с проблемой - доставкой исключений.Исключение должно быть уведомлено вызывающей стороне из того места, где оно изначально возникло, чтобы обеспечить правильную обработку исключений. Вы можете подумать, что это сложно, но на самом деле передача исключений в Python очень проста и интуитивно понятна.

1. попробуйте вложенный проход

В Python, если мы не используем, кроме обработки исключений, то исключения будут 外层переданы в " ".
Первый процесс доставки должен передать внешний уровень оператора try.Если во внешнем уровне есть другой оператор try, вложенный во внешний уровень, внешний оператор try перехватит это исключение. См. пример ниже:

import time

try:

    f = open('test.txt')

    try:

        print(num)

    finally:

        f.close()

        print('关闭文件')

except:

    print("发生了错误")

Если в том же каталоге, что и этот файл кода, нет файла ' test.txt' , мы получим следующие результаты при его запуске:

вставьте сюда описание изображения
Когда ' test.txt' существует, запустите приведенный выше код, и мы увидим следующий результат:

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

Подводя итог : для кода, содержащегося в try, если для перехвата исключения не используется исключение, исключение будет передано внешнему уровню до тех пор, пока оно не встретит попытки и исключения следующего уровня.

2. Передача вызова функции

Использование множественных вложенных исключений try — это код, который мы редко пишем. В реальных проектах мы чаще видим: при многоуровневом вызове функции вызываемая функция имеет исключение.
Как и в предыдущем примере, если исключение не перехвачено в функции, оно будет передаваться вызывающему объекту функции слой за слоем, пока не встретит попытку и соответствующее исключение для его перехвата. Рассмотрим следующий пример:

def test1():

    print("----test1-1----")

    print(num)

    print("----test1-2----")
def test2():

    print("----test2-1----")

    test1()

    print("----test2-2----")

def test3():

    try:

        print("----test3-1----")

        test1()

        print("----test3-2----")

    except Exception as result:

        print("捕获到了异常,信息是:%s" % result)

 

    print("----test3-2----")

test3()

print("------华丽的分割线-----")

test2()

print("这里永远也不会被执行")

Результат после запуска следующий:

вставьте сюда описание изображения
Можно видеть, что когда test3() вызывается в первый раз, исключение, сгенерированное в test1(), перехватывается функцией try...except...in test3(), и выводится сообщение об ошибке. Система продолжает выполняться, и во втором test2() нет обработки исключений, затем исключение test1() передается вверх до тех пор, пока не останется кода для его обработки, и программа окончательно прервется. Это передача вызова функции и требует от вас понимания памяти.
вставьте сюда описание изображения

4. Пользовательские исключения

1. Используйте повышение, чтобы создать пользовательское исключение

Мы научились перехватывать и обрабатывать исключения.В то же время мы также можем активно передавать исключения внешнему вызывающему объекту для написанной нами логики кода, также называемой " ", чтобы сообщить другим, что программа сгенерировала ошибку 抛出异常.
Мы уже знаем, что все исключения являются подклассами встроенного в Python класса Exception, поэтому мы можем определить класс, наследуемый от Exception, как пользовательское исключение, как показано ниже:

class ShortInputException(Exception):

    '''自定义的异常类'''

    def __init__(self, length, atleast):

        #super().__init__()

        # 我们可以向类中添加属性

        self.length = length

        self.atleast = atleast

В Python мы можем использовать оператор повышения для создания исключения, продолжая наш пример:

class ShortInputException(Exception):

    '''自定义的异常类'''

    def __init__(self, length, atleast):

        #super().__init__()

        # 我们可以向类中添加属性

        self.length = length

        self.atleast = atleast
def main():

    try:

        s = input('请输入 --> ')

        if len(s) < 3:

            # raise 引发一个你定义的异常

            raise ShortInputException(len(s), 3)

    except ShortInputException as result:#x 这个变量被绑定到了错误的实例

        print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast))

    else:

        print('没有异常发生.')
main()

Результат операции следующий:

вставьте сюда описание изображения
В приведенном выше коде сначала мы настроили класс исключения ShortInputException, который наследует родительский класс Exception, затем, когда мы используем в коде raise ShortInputException для выбрасывания исключения, в последующем exclude мы указываем тип полученного исключения как ShortInputException, вы можете его перехватить; наконец, мы присваиваем объект исключения переменной результата через оператор as. Таким образом, мы можем получить доступ к его длине и, по крайней мере, свойствам в теле исключения.

Обратите внимание : В приведенной выше программе описание кода #super(). init ():
эта строка кода может быть вызвана или нет. Но рекомендуется вызывать именно его, потому что метод __init__ обычно используется для инициализации создаваемого объекта.Если метод __init__ родительского класса переписан в подклассе, значит, много работы по инициализации в родительском классе не выполняется. не гарантирует стабильность работы программы. Так что в вашей будущей разработке, если вы переписываете метод __init__ родительского класса, лучше всего сначала вызывать этот метод родительского класса, а затем добавлять свои собственные функции.

вставьте сюда описание изображения

5. Ненормальное приложение и резюме

1. Необычное приложение

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

  1. Пользовательский ввод: не уверен, какие данные пользователь введет, чтобы вызвать ошибку
  2. Сетевое соединение: сетевое соединение может быть прервано
  3. Чтение и запись файла: файл может не существовать
  4. Поиск в базе данных: данные, которые вы хотите найти, могут не существовать
  5. Удаленный вызов API: входные параметры, URL-адрес и т. д. могут быть неверными или служба другой стороны может иметь ошибку

Подождите, есть много других необычных сценариев применения

2. Принцип обработки исключений

Когда вы сталкиваетесь с квалифицированным сценарием исключения, вы можете использовать ry для перехвата исключения. После отлова, как бороться с исключением? Наш принцип: "Пусть программа возобновит работу".

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

Вы можете посмотреть код, который вы написали в прошлом, чтобы увидеть, где в системе могут быть неопределенные ошибки. Затем попробуйте добавить попытку, кроме обработки исключений, чтобы ваша система могла правильно реагировать и работать стабильно.

вставьте сюда описание изображения

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

Supongo que te gusta

Origin blog.csdn.net/weixin_57577264/article/details/120686077
Recomendado
Clasificación