Исключение FileNotFoundError и менеджер контекста (with) для файлов
На предыдущем занятии я отмечал, что если указать неверный путь к файлу, то возникнет ошибка:
и программа досрочно прерывается. Это неприятный момент, тем более, что программист наперед не может знать, в каких условиях будет работать программа и вполне возможна ситуация, когда ранее доступный файл становится недоступным, например, из-за случайного его удаления, или изменении имени и т.п. То есть, при работе с файлами нужно уметь обрабатывать исключение FileNotFoundError, чтобы программа продолжала работать, даже если файл не будет найден.
Для обработки подобных ошибок (или, как говорят, исключений) существует специальная группа операторов:
о которых мы подробно будем говорить в части объектно-ориентированного программирования на Python. Но, несмотря на то, что это выходит за рамки базового курса, я решил показать, как использовать эти операторы при работе с файлами. Иначе, ваши программы будут заведомо содержать серьезную уязвимость при обращении к файлам.
Формально, операторы try / except / finally имеют, следующий синтаксис (определение):
try:
блок операторов
критического кода
except [исключение]:
блок операторов
обработки исключения
finally:
блок операторов
всегда исполняемых
вне зависимости, от
возникновения исключения
И в нашем случае их можно записать, так:
try: file = open("my_file.txt", encoding='utf-8') s = file.readlines() print(s) file.close() except FileNotFoundError: print("Невозможно открыть файл")
Смотрите, здесь функция open() находится внутри блока try, поэтому, если возникнет исключение FileNotFoundError, то выполнение программы перейдет в блок except и отобразится строка «Невозможно открыть файл». Иначе, мы прочитаем все строки из файла, отобразим их в консоли и закроем файл.
Однако, и в такой реализации не все гладко. В момент считывания информации из файла (в методе readlines()) также может возникнуть исключение из-за невозможности считывания информации из файла. Поэтому, совсем надежно можно было бы реализовать эту программу, следующим образом:
try: file = open("my_file.txt", encoding='utf-8') try: s = file.readline() print(s) finally: file.close() except FileNotFoundError: print("Невозможно открыть файл") except: print("Ошибка при работе с файлом")
Мы здесь прописываем еще один вложенный блок try, который будет учитывать все возможные исключения и при их возникновении мы обязательно перейдем в блок finally для закрытия файла. Это важная процедура – любой ранее открытый файл (функцией open()) следует закрывать, даже при возникновении исключений. И вот такая конструкция try / finally нам гарантирует его закрытие, что бы ни произошло в момент работы с ним. Но блок try / finally не отлавливает исключения, поэтому они передаются внешнему блоку try и здесь мы должны их обработать. Я сделал это через второй блок except, в котором не указал никакого типа исключений. В результате, он будет реагировать на любые не обработанные ошибки, то есть, в нашем случае – на любые ошибки, кроме FileNotFoundError.
Менеджер контекста для файлов
Более я не буду углубляться в работу блоков try / except / finally. Приведенного материала пока вполне достаточно, а в заключение этого занятия расскажу о замене блока try / finally так называемым файловым менеджером контекста, как это принято делать в программах на Python.
Так вот, в языке Python существует специальный оператор with, который, можно воспринимать как аналог конструкции try / finally и в случае работы с файлами записывается, следующим образом:
try: with open("my_file.txt", encoding='utf-8') as file: s = file.readlines() print( s ) except FileNotFoundError: print("Невозможно открыть файл") except: print("Ошибка при работе с файлом")
Смотрите, мы здесь сразу вызываем функцию open(), создается объект file, через который, затем, вызываем методы для работы с файлом. Причем, все операторы должны быть записаны внутри менеджера контекста, так как после его завершения файл закрывается автоматически. Именно поэтому здесь нет необходимости делать это вручную.
При работе с менеджером контекста следует иметь в виду, что он не обрабатывает никаких ошибок (исключений) и все, что происходит, передается вышестоящему блоку try, где они и обрабатываются. Но в любом случае: произошли ошибки или нет, файл будет автоматически закрыт. В этом легко убедиться, если добавить блок finally для оператора try, в котором отобразить флаг закрытия файла:
try: with open("my_file.txt", encoding='utf-8') as file: s = file.readlines() print( s ) except FileNotFoundError: print("Невозможно открыть файл") except: print("Ошибка при работе с файлом") finally: print(file.closed)
После запуска программы видим значение True, то есть, файл был закрыт. Даже если произойдет критическая ошибка, например, вызовем функцию int() для строки s:
то, снова видим значение True – файл был закрыт. Вот в этом удобство использования менеджера контекста при работе с файлами.
На этом мы завершим наше ознакомительное занятие по обработке файловых ошибок. Пока будет достаточно запомнить использование операторов try / except / finally при работе с файлами, а также знать, как открывать файлы через менеджер контекста. На следующем уроке мы продолжим тему файлов и будем говорить о способах записи данных.
Видео по теме
#1. Первое знакомство с Python Установка на компьютер
#2. Варианты исполнения команд. Переходим в PyCharm
#3. Переменные, оператор присваивания, функции type и id
#4. Числовые типы, арифметические операции
#5. Математические функции и работа с модулем math
#6. Функции print() и input(). Преобразование строк в числа int() и float()
#7. Логический тип bool. Операторы сравнения и операторы and, or, not
#8. Введение в строки. Базовые операции над строками
#9. Знакомство с индексами и срезами строк
#11. Спецсимволы, экранирование символов, row-строки
#12. Форматирование строк: метод format и F-строки
#13. Списки — операторы и функции работы с ними
#14. Срезы списков и сравнение списков
#15. Основные методы списков
#16. Вложенные списки, многомерные списки
#17. Условный оператор if. Конструкция if-else
#18. Вложенные условия и множественный выбор. Конструкция if-elif-else
#19. Тернарный условный оператор. Вложенное тернарное условие
#21. Операторы циклов break, continue и else
#22. Оператор цикла for. Функция range()
#23. Примеры работы оператора цикла for. Функция enumerate()
#24. Итератор и итерируемые объекты. Функции iter() и next()
#25. Вложенные циклы. Примеры задач с вложенными циклами
#26. Треугольник Паскаля как пример работы вложенных циклов
#27. Генераторы списков (List comprehensions)
#28. Вложенные генераторы списков
#29. Введение в словари (dict). Базовые операции над словарями
#30. Методы словаря, перебор элементов словаря в цикле
#31. Кортежи (tuple) и их методы
#32. Множества (set) и их методы
#33. Операции над множествами, сравнение множеств
#34. Генераторы множеств и генераторы словарей
#35. Функции: первое знакомство, определение def и их вызов
#36. Оператор return в функциях. Функциональное программирование
#37. Алгоритм Евклида для нахождения НОД
#38. Именованные аргументы. Фактические и формальные параметры
#39. Функции с произвольным числом параметров *args и **kwargs
#40. Операторы * и ** для упаковки и распаковки коллекций
#42. Анонимные (lambda) функции
#43. Области видимости переменных. Ключевые слова global и nonlocal
#45. Введение в декораторы функций
#46. Декораторы с параметрами. Сохранение свойств декорируемых функций
#47. Импорт стандартных модулей. Команды import и from
#48. Импорт собственных модулей
#49. Установка сторонних модулей (pip install). Пакетная установка
#50. Пакеты (package) в Python. Вложенные пакеты
#51. Функция open. Чтение данных из файла
#52. Исключение FileNotFoundError и менеджер контекста (with) для файлов
#53. Запись данных в файл в текстовом и бинарном режимах
#55. Функция-генератор. Оператор yield
#56. Функция map. Примеры ее использования
#57. Функция filter для отбора значений итерируемых объектов
#58. Функция zip. Примеры использования
#59. Сортировка с помощью метода sort и функции sorted
#60. Аргумент key для сортировки коллекций по ключу
#61. Функции isinstance и type для проверки типов данных
#62. Функции all и any. Примеры их использования
#63. Расширенное представление чисел. Системы счисления
#64. Битовые операции И, ИЛИ, НЕ, XOR. Сдвиговые операторы
#65. Модуль random стандартной библиотеки
#66. Аннотация базовыми типами
#67. Аннотации типов коллекций
#68. Аннотации типов на уровне классов
#69. Конструкция match/case. Первое знакомство
#70. Конструкция match/case с кортежами и списками
#71. Конструкция match/case со словарями и множествами
#72. Конструкция match/case. Примеры и особенности использования
© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта