Как сделать файловый менеджер на python

Обновлено: 28.06.2024

В этой статье вы узнаете как организовать работать с файлами в Python 3.

Создайте файл files.py и копируйте туда код из примеров.

Запустить файл можно командой python3 files.py

Создать

Создать файл можно командой open

rb чтение в бинарном режиме

w только запись.

wb запись в бинарном режиме

w+ запись и чтение

a запись в конец файла - сохранит данные, которые были в файле

Любая опция с w перезапишет существующий файл - будьте внимательны!

f = open ("log.txt","w+")

Открыть файл

Чтобы открыть файл для чтения выполните

f = open ("log.txt","r")

Если файл log.txt не существует, он не будет создан

raceback (most recent call last): File "files.py", line 1, in f = open('log.txt', 'r') FileNotFoundError: [Errno 2] No such file or directory: 'log.txt'

Закрыть файл

Чтобы закрыть файл выполните

Имя файла

Пример программы, которая выводит на экран имя файла и режим, в котором он открыт

f = open ('text.txt', 'r') print (f.name) print (f.mode) f.close()

Если файл log.txt существует, то в терминале вы увидите

Менеджер контекста

Предпочтительнее использовать менеджер контекста для работы с файлами

Как только вы выйдете из блока в котором открыт файл - он автоматически закроется

with open ('text.txt', 'r') as f: pass print (f.closed)

Прочитать содержимое файла

with open ('sites.txt', 'r') as f: f_contents = f.read() print (f_contents)

Все строки с символом перехода на новую строку - readlines

with open ('sites.txt', 'r') as f: f_contents = f.readlines() print (f_contents)

Строки по одной readline

with open ('sites.txt', 'r') as f: f_contents = f.readline() print (f_contents) f_contents = f.readline() print (f_contents)

Строки по одной без лишних переходов end=''

with open ('sites.txt', 'r') as f: f_contents = f.readline() print (f_contents, end = '') f_contents = f.readline() print (f_contents, end = '')

Цикл для построчного вывода

with open ('sites.txt', 'r') as f: for line in f: print (line, end = '')

Прочитать определённое количество символов

with open ('sites.txt', 'r') as f: f_contents = f.read(20) print (f_contents)

Если выполнять эту команду последовательно - будут прочитаны следующие символы

with open ('sites.txt', 'r') as f: f_contents = f.read(20) print (f_contents, end = '') f_contents = f.read(20) print (f_contents, end = '')

Цикл для произвольного количества символов .read

with open ('sites.txt', 'r') as f: size_to_read = 10 f_contents = f.read(size_to_read) while len(f_contents) > 0: print (f_contents, end = '') f_contents = f.read(size_to_read)

Выражение f_contents = f.read(size_to_read) нужно для того, чтобы когда файл закончится и f.read(size_to_read) станет нулем len(f_contents) тоже станет нулем и цикл завершится

Перейти в произвольное место seek

Например, вернуться в начало файла

Копирование файлов

Текстовые файлы

Их можно копировать построчно

with open ('sites.txt', 'r') as rf: with open ('sites_copy.txt', 'w') as wf: for line in rf: wf.write(line)

Изображения

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

with open ('stels_pilot_950_MD_26.jpg', 'rb') as rf: with open ('stels_pilot_950_MD_26_copy.jpg', 'wb') as wf: for line in rf: wf.write(line)

python3 files.py
ls

Более правильным подходом считается копирование не в построчном режиме а частями с фиксированным размером

with open ('stels_pilot_950_MD_26.jpg', 'rb') as rf: with open ('stels_pilot_950_MD_26_copy.jpg', 'wb') as wf: chunk_size = 4096 rf_chunk = rf.read(chunk_size) while len(rf_chunk) > 0: wf.write(rf_chunk) rf_chunk = rf.read(chunk_size)

Записать файл

Чтобы очистить файл от старого содержимого и записать в него новое используется опция w (write)

with open ('log.txt', 'w') as f: f.write("some text")

Дописать в файл

Если нужно добавить новые данные к предыдущему содержимому без удаления - используется опция a (append)

10 самых продуктивных техник для работы с файлами в Python

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

1. Показ текущей директории

Чтобы узнать текущую рабочую директорию, мы можем просто ввести функцию getcwd() модуля os, как показано ниже:

Данный код также демонстрирует возможность использования модуля pathlib для получения текущей рабочей директории. Обратите внимание, что для выполнения операций с файлами именно этот модуль является предпочтительным вариантом, и в статье вас ждёт немало примеров его употребления. Однако, если у вас устаревшая версия Python ( os .

2. Создание новой директории

Для создания новой директории можно применить функцию mkdir() , которая выполнит эту операцию по конкретно заданному пути. Если вы просто укажете имя новой директории, то она будет создана в текущем каталоге:

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

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

Имейте в виду, что попытка повторного выполнения вышеприведённого кода может вызвать проблемы — вы не сможете создать новую директорию, если такая уже существует. Стоит отметить, что эта проблема решается путём присвоения аргументу exist_ok значения True , как показано выше. А вот значение False , установленное для него по умолчанию, не позволит повторно создать уже существующую директорию и приведёт к ошибке.

3. Удаление директорий и файлов

По завершении операций с файлами или папками, возможно, потребуется их удалить, чтобы упорядочить ресурсы компьютера. Для удаления файла в модуле os применяется функция remove() , а для удаления папки — функция rmdir() . Попытка же удалить директорию с помощью remove() вызовет ошибку. Рассмотрим применение этих функций:

При использовании модуля pathlib за удаление файла отвечает метод unlink() , а за удаление директории — rmdir() . Обратите внимание, что они оба являются методами экземпляра объекта Path .

4. Получение списка файлов

В процессе обработки данных для аналитики или проектов МО вам потребуется получить список файлов в определённой директории. Зачастую их имена соответствуют определённому шаблону. Допустим, мы хотим найти все файлы .txt в директории. Далее рассмотрим, как это можно сделать с помощью метода glob() с объектом Path . Обратите внимание, что данный метод создаёт генератор с возможностью итерации. Следующий код наглядно демонстрирует создание генератором списка путей файлов:

Как вариант, также удобно использовать модуль glob напрямую, как показано ниже. Он располагает аналогичной функциональностью, создавая списки имён файлов, с которыми впоследствии можно работать. Заметьте, что Path.glob() создаёт пути. Оба метода будут работать в большинстве сценариев, таких как чтение и запись файлов.

5. Перемещение и копирование файлов

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

Копирование же можно выполнить при помощи функциональности, доступной в shutil, ещё одном полезном модуле из стандартной библиотеки для операций с файлами. Здесь за это отвечает функция copy() , в которой исходный и целевой файлы указываются в виде строк. Ниже вы увидите простой пример. Конечно, вы можете объединить функции copy() и glob() для работы с группой файлов, соответствующих одному паттерну.

6. Проверка директории/файла

На самом деле, эта операция уже много раз встречалась в вышеприведённых примерах. В них для проверки того, существует ли конкретный путь, применялся метод exists() . При условии положительного ответа он возвращает True , в противном случае — False . Примечательно, что эта функция доступна в обоих модулях, os и pathlib, но с разными сигнатурами. Рассмотрим соответствующие примеры их применения:

В модуле pathlib можно также проверить, является ли путь директорией или файлом с готовыми к вызову функциями. Обратимся к следующему примеру:

7. Получение информации о файле

При работе с файлами во многих сценариях возникает необходимость извлечения их имён. С объектом Path это просто как дважды два, и вы уже были свидетелями его применения. Можно просто извлечь атрибут name файлового объекта Path . Если же вам нужно узнать только имя без расширения, то извлекать следует атрибут stem . Следующий фрагмент кода демонстрирует соответствующие случаи применения:

В отдельных случаях вам потребуется узнать расширение файла, с которым вы работаете. Чаще всего можно воспользоваться атрибутом suffix файлового объекта Path , как показано ниже:

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

8. Чтение файлов

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

Этот код демонстрирует самые распространённые способы чтения содержимого. Если вы знаете, что ваш файл включает немного данных, можете считать их все за раз с помощью метода read() . Но если он очень крупный, то следует рассмотреть вариант с генератором, роль которого выполняет файловый объект. Он обрабатывает данные построчно и тем самым экономно расходует память, обходясь без загрузки всех данных при применении read() .

Как уже ранее упоминалось, функция open() по умолчанию работает с содержимым файла как с текстом. Однако в случае с бинарными файлами необходимо явно задать данное условие. Например, вместо ‘r’ следует ввести ‘rb’ . Это требование также относится и к записи файлов, о чём мы поговорим далее. Ещё один непростой момент связан с кодировкой файла. Во многих случаях функция open() сможет выполнить эту операцию за нас, и большинство файлов, с которыми мы работаем, будут в кодировке “utf-8”. Если же вы обрабатываете файлы, применяя другие форматы кодировки, вам следует установить аргумент encoding .

9. Запись файлов

Для записи данных можно опять же создать файловый объект, открыв файл в режиме записи ( ‘w’ ) или дозаписи ( ‘a’ ). В первом случае при записи данных в файл его старое содержимое удаляется, а во втором — данные добавляются в конец файла. Рассмотрим пример работы этих двух режимов в следующем фрагменте кода.

Этот код подтверждает, что мы можем записывать данные в двух режимах: записи и дозаписи. Обратили вы внимание или нет, но каждый раз при открытии файла использовалась инструкция with . Объясняется это тем, что она создаёт контекст для обработки файла и помогает закрыть файловый объект по завершении операций. Если же вовремя этого не сделать, то открытый файловый объект может повредиться.

10. Архивирование и разархивирование файлов

При работе с большим числом файлов может потребоваться их архивирование для долгосрочного хранения или временной передачи. Соответствующие возможности предоставляются модулем zipfile. Для архивирования файлов функцией ZipFile() создаётся файловый объект zip, что напоминает случай с функцией open() , поскольку обе эти функции предусматривают создание файлового объекта, управляемого контекстным менеджером (вспоминаете применение инструкции with ?). Обратимся к фрагменту кода с простым примером:

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

Заключение

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

11 проектов, которые должен разработать каждый питонист

Контент помогает нам принимать решения − весь поток информации, публикуемый в блогах, соцсетях, на экране, является контентом. Единственный способ оставаться в курсе событий, не терять компетенцию − постоянно потреблять контента. Но поиск утомителен.

Для этого создают агрегаторы контента. Их суть в том, чтобы собирать разные, релевантные вам статьи, посты в соцсетях и собирать всё в одном месте.

Примеры реализации

Техническая реализация

Чтобы агрегация контента происходила в фоновом режиме, стоит обратить внимание на библиотеки Celery или Apscheduler.

А еще подумайте о базе данных, в которой будет храниться собранная информация.

Regex Query Tool

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

С помощью инструмента Regex Query Tool пользователи могут быстро проверить правильность своих строк регулярных выражений в интернете.

Было бы неплохо добавить функцию замены совпадений.

Примеры реализации

Техническая реализация

Такие проекты на Python нужны, чтобы сообщать пользователю, правильно ли он ввёл данные. Можно сделать так, чтобы сервис давал положительный или отрицательный ответ, вроде Query String Is Valid , выделяя положительный ответ зеленым цветом, а отрицательный − красным.

Реализовывать инструмент запросов с нуля необязательно. Можно обратиться к стандартной библиотеке Re. Она будет возвращать None при отсутствии совпадений или возвращать совпавшие строки.

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

URL Shortener

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

А еще Google прекратил поддержку своего сервиса goo.gl, так что у вас есть шанс сделать свой продукт популярнее.

Примеры реализации

Техническая реализация

Основная задача, которую будет выполнять приложение, заключается в сокращении URL-адресов с последующей переадресацией на исходный URL-адрес.

В приложении пользователи будут вводить исходный URL-адрес и в результате получат новый сокращенный URL-адрес. Для этого стоит использовать комбинацию random и string .

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

Post-It Note

Мы постоянно о чём-то думаем, а ещё постоянно забываем. Один из способов запомнить − записать, чтобы обдумать позднее.

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

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

Примеры реализации

Техническая реализация

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

Django поставляется с системой аутентификации пользователя, так что это может быть одним из способов реализации идеи. Можно также использовать другие фреймворки, например, Bottle или Flask. Но вы должны самостоятельно внедрить систему аутентификации пользователей.

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

Опять же, вам нужно где-то хранить поступающую информацию. Для MySQL можно использовать MySQLdb, а для PostgreSQL − Psycopg2.

Викторина

11 проектов, которые должен разработать каждый питонист

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

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

Примеры реализации

Техническая реализация

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

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

Сигнализация

Идея в том, чтобы имитировать звук сигнализации при каком-либо условии. Этим условием может быть наступление какого-то времени или разрядка ноутбука до 10%.

Примеры реализации

Техническая реализация

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

Для воспроизведения аудио можно использовать библиотеку Pygame.

Файловый менеджер

11 проектов, которые должен разработать каждый питонист

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

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

Кстати, неплохо бы добавить разные варианты просмотра и сортировки файлов, поиск.

Примеры реализации

Техническая реализация

Для создания уникальных пользовательских интерфейсов стоит использовать библиотеку PySimpleGUI.

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

При реализации проекта стоит обратить внимание на библиотеки Sys, OS и Shutil. Они позволяют выполнять процессы в фоновом режиме, пока пользователь занимается чем-то другим.

Контроль расходов

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

Наиболее продвинутые из них не просто показывают список трат за определённы период, но и подсказывают, какие категории расходов стоит сократить.

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

Было бы неплохо добавить напоминания о необходимости анализа расходов.

Примеры реализации

Техническая реализация

Для построения системы отслеживания расходов могут пригодиться Pandas и Matplotlib.

Pandas − для анализа данных, а Matplotlib − для построения графиков. Графики дают пользователям визуальное представление о своих расходах, а визуальное представление обычно легче понять.

Что касается хранения информации, то стоит обратиться к SQLite и её модулю SQlite3.

Контакты

Вы еще записываете контакты на бумагу? Странная затея: блокнот может потеряться, и его нужно носить с собой.

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

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

Примеры реализации

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

Техническая реализация

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

Значительную часть работы будут выполнять Argparse и Click. Вам остаётся только подумать о логике выполнения команд. Вам также нужно реализовать удаления контактов, обновление информации и вывод списка сохранённых. Идеально, если они будут сортироваться по алфавиту или дате создания.

Проверка подключения к сайту

11 проектов, которые должен разработать каждый питонист

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

Здесь на помощь приходит приложение для проверки подключения к сайту. Сервис анализирует статус URL-адреса и сообщает его. Так можно не обновлять страницу N раз в ожидании загрузки сайта.

Но! Если отображать результаты в командной строке, пользователю нужно будет обновлять её вручную. Лучше потратить больше времени и реализовать уведомления о появлении доступа к сайту.

Примеры реализации

Техническая реализация

Для подключений можно использовать TCP или ICMP. Один из модулей, которые нужно проверить − Socket.

Фреймворки Docopt, Click или Argparse позволят изменять список сайтов для проверки. Ещё подумайте о введении интервалов для проверки, чтобы не перегружать систему.

Изменение имени файлов

Иногда все файлы в папке должны называться примерно одинаково. Например, File0001.jpg, где номера увеличиваются в зависимости от количества файлов в каталоге. Делать это вручную утомительно.

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

Кстати, иногда нужно переименовать лишь часть файлов в папке. Хорошо, если такая функция тоже будет.

Примеры реализации

Техническая реализация

Для манипуляций с файлами пригодятся библиотеки OS, Sys и Shutil.

Чтобы сервис понял, по какой системе нужно менять названия файлов, дайте ему шаблон. Если вы понимаете, как работают регулярные выражения, воспользуйтесь модулем Regex.

Банальная задача − назвать файлы по списку или привести их в общий вид путем изменения MyfilesXYZ, где XYZ − число. Это должно быть базовой функцией, чтобы не усложнять пользователям жизнь.

Понравилось разрабатывать подобные проекты на Python? Вам понравится:

Источник: Проекты на Python, которые сможет разработать любой Middle Python Developer на Realpython.


Несколько лет назад, в Python 2.5 добавили новое ключевое слово, под названием оператор with. Это новое ключевое слово позволяет разработчику создавать контекстные менеджеры. Но подождите, что же такое контекстный менеджер? Это удобные конструкции, которые позволяют разработчику настраивать что-нибудь и разрывать в автоматическом режиме. Например, вам может потребоваться открыть файл, вписать в него кучу всего и закрыть. Это классический пример работы контекстного менеджера. Фактически, Python создает один такой экземпляр автоматически каждый раз, когда вы открываете файл, используя оператор with:

В Python 2.4, вам нужно делать это старомодным способом:

Это работает путем использования двух волшебных методов Python: __enter__ и __exit__. Давайте попробуем создать собственный контекстный менеджер, чтобы увидеть, как это работает на практике.

Создаем класс Context Manager

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

В данном коде мы создали класс, который берет путь к файлу базы данных SQLite Python. Метод __enter__ выполняется автоматически, он создает и возвращает объект связи базы данных. Теперь мы можем создать курсор для записи в базу данных или чтобы её запросить. Когда мы выходим из оператора with, метод __exit__ запускается, закрывая таким образом связь. Давайте попробуем создать контекстный менеджер при помощи другого метода.

Создание контекстного менеджера с использованием contextlib

В Python 2.5 добавили не только оператор with, но также модуль contextlib. Это позволяет нам создать контекстный менеджер, используя функцию модуля contextlib под названием contextmanager в качестве декоратора. Давайте попробуем создать контекстный менеджер который открывает и закрывает файл после проделанной в нем работе:

Здесь мы просто импортируем contextmanager из contextlib и декорируем нашу функцию file_open с ним. Это позволяет нам вызвать file_open используя оператор with. В нашей функции мы открываем файл, отдаем его, чтобы функция calling могла использовать его. После того, как оператор закончит, контроль возвращается обратно к функции file_open, которая продолжает следовать по коду за вызываемым оператором. Это приводит оператор finally к исполнению, благодаря которому и закрывается файл. Если возникла ошибка OSError во время работы с файлом, она будет выявлена и оператор finally закроет обработчик файлов несмотря на это.

contextlib.closing()

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

В целом, мы создаем закрывающую функцию, которая завернута в контекстный менеджер. Это эквивалент того, что делает класс closing. Но есть небольшая разница: вместо декоратора, мы можем использовать класс class в нашем операторе with. Давайте взглянем:

В данном примере мы открыли страницу URL, но обернули её в наш класс closing. Это приведет к закрытию дескриптора веб-страницы, сразу после выхода из блока кода оператора with.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

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

contextlib.suppress(*exceptions)

Еще один полезный инструмент — класс suppress, который был добавлен в Python 3.4. Идея в том, что данная утилита контекстного менеджера может подавлять любое количество исключений. Скажем, нам нужно проигнорировать исключение FileNotFoundError. Если прописать следующий контекстный менеджер, то это не сработает:

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

Здесь мы импортируем suppress и передаем его исключению FileNotFoundError. Если вы запустите этот код, вы увидите, что ничего не происходит, так как файл не существует, но и ошибка не возникает. Обратите внимание на то, что этот контекстный менеджер является реентрабельным, но об этом позже.

contextlib.redirect_stdout / redirect_stderr

С модулем contextlib вы можете сделать следующее:

ExitStack

ExitStack – это контекстный менеджер, который позволит вам легко комбинировать другие контекстные менеджеры, а также функции очистки. Звучит немного запутанно, на первый взгляд, так что давайте рассмотрим простой пример из документации Python, с его помощью будет проще уловить суть:

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

  • Выявление исключений из методов __enter__
  • Поддержки переменного количества контекстных менеджеров
  • Замена любого применения try-finally
  • И многое другое!

Я настоятельно рекомендую ознакомиться с этими темами, так как вы поймете, насколько эффективным и полезным может быть этот класс.

Реентерабельные контекстные менеджеры

Большая часть создаваемых вами контекстных менеджеров может быть написана только для использования с оператором with для одноразового применения. Вот пример:

Здесь мы создали экземпляр контекстного менеджера и пытаемся запустить его дважды с оператором with. Второй запуск приводит к ошибке RuntimeError. Но что делать, если нам необходимо, чтобы контекстный менеджер запускался дважды? Для этой цели нам и нужен реентрабельный контекстный менеджер. Давайте используем менеджер redirect_stdout, который мы применяли ранее.

Здесь мы создали вложенные контекстные менеджеры, которые оба пишут в StringIO, который является текстовым потоком в памяти. Причина, по которой это работает, а не приводит к ошибке RuntimeError, как было ранее в том, что redirect_stdout является реентрабельным и позволяет нам вызывать его дважды. Конечно, ситуации в реальной жизни могут быть заметно сложнее, когда мы работаем с большим количеством функций, которые вызывают друг друга. Пожалуйста, обратите также внимание на то, что контекстные менеджеры не обязательно являются защищенными от потоков. Обратитесь к документации, перед тем как использовать их в потоках во избежание путаницы.

Подведем итоги

Контекстный менеджер – крайне полезный и удобный инструмент, способный выручить во многих ситуациях. Я пользуюсь ими в своих автоматических тестах постоянно, для открытия и закрытия диалогов, например. Теперь вы можете использовать ряд встроенных в Python инструментов для создания собственных контекстных менеджеров. Убедитесь в том, что вы выделили достаточно времени для изучения документации Python о contextlib, так как в ней хранится очень много дополнительной полезной информации, которая не была рассмотрена в данной статье.


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

Читайте также: