Как открыть файл с помощью Python

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

Оператор with создает менеджер контекста, который упрощает способ открытия и закрытия файлов в программах Python. Без использования оператора with разработчик должен помнить о необходимости закрыть обработчики файлов. Это автоматически делается Python при использовании шаблона with open … as.

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

Давайте начнем!

Синтаксис открытия файла в Python без использования оператора With

Я создал файл output.txt со следующим содержимым:

$ cat output.txt 
Line1
Line2
Line3
Line4
Line5

Давайте посмотрим на определение функции open из документации Python:

Открытая функция Python

В этом руководстве мы сосредоточимся на первых двух аргументах функции open: file и mode.

Вот как мы можем открыть наш файл в режиме чтения, используя функцию open.

Режим чтения установлен по умолчанию.

>>> f = open('output.txt')
>>> f.read()
'Line1\nLine2\nLine3\nLine4\nLine5\n'
>>> f.close()
>>> f.closed
True

Мы используем функцию open для создания обработчика файла (f), а затем используем обработчик файла для чтения содержимого файла с помощью функции read().

После прочтения содержимого файла мы используем функцию close() для закрытия обработчика.

Запустив f.closed, мы получим True как подтверждение того, что обработчик файлов закрыт.

Давайте посмотрим, как выглядит объект файла в предыдущем примере:

>>> f = open('output.txt')
>>> print(f)
<_io.TextIOWrapper name='output.txt' mode='r' encoding='UTF-8'>
>>> print(f.__dict__)
{'mode': 'r'} 

Он имеет тип TextIOWrapper, его кодировка по умолчанию — UTF-8, и у него есть атрибут mode.

Чтобы узнать, какие методы можно использовать для этого файлового объекта, выполните следующую команду в оболочке Python:

>>> help(f)

Примечание: Режим чтения — это режим по умолчанию, используемый Python для открытия файлов, если только вы не передадите второй параметр в функцию открытия (см. несколько примеров ниже):

РежимПример
r (чтение – текстовый формат)f = open(filename, 'r')
rb (чтение – двоичный формат)f = open(filename, 'rb')
w (запись – текстовый формат, обрезает файл)f = open(filename, 'w')
wb (запись – двоичный формат, обрезает файл)f = open(filename, 'wb')
r+ (чтение и запись – текстовый формат)f = open(filename, 'r+')
a (append – текстовый формат, добавляет в конец файла)f = open(filename, 'a')

Как прочитать файл с помощью with open … as в Python

Давайте посмотрим, что произойдет, если мы используем оператор with при открытии файлов в Python.

Синтаксис, который мы будем использовать, следующий:

with open(file, mode) as file_object

При использовании оператора with файл автоматически закрывается, когда он больше не нужен. Это подтверждается тем фактом, что в следующем коде f.closed возвращает True.

>>> with open('output.txt') as f:
...     data = f.read()
... 
>>> f.closed
True

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

Итак, подведем итоги…

Если вы не используете ключевое слово with, вам нужно помнить о вызове f.close() для освобождения ресурсов, когда файл вам больше не нужен. Запуск f.close() не требуется при использовании оператора with.

Что произойдет, если мы попытаемся прочитать файл, который уже закрыт?

>>> f.closed
True
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.

Python вызывает исключение ValueError.

Распечатать все строки в файле с помощью with open … as

Давайте выясним, как распечатать все строки файла после открытия файла с помощью оператора with.

Мы будем использовать файл output.txt, использованный в предыдущем примере, и перебирать строки в файле по одной:

with open('output.txt', 'r+') as f:
    for line in f:
        print(line)

Мы передали r+ в качестве второго параметра, чтобы открыть файл для чтения и записи.

Как вы можете видеть, я использую цикл for для прохода по строкам файла, используя файловый объект.

$ python with_open_example.py 
Line1

Line2

Line3

Line4

Line5

По какой-то причине оператор печати добавляет новые символы строки, которых нет в исходном файле.

Чтобы избавиться от них, можно использовать следующий синтаксис:

print(line, end='')

Наш код становится следующим:

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

[output]
$ python with_open_example.py 
Line1
Line2
Line3
Line4
Line5 

Теперь выглядит хорошо 🙂

Открытие нескольких файлов в одном операторе with

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

Например, предположим, что у нас есть следующий список:

items = ['dog', 'cat', 'apple', 'pear', 'lion', 'banana']

И наша программа должна записывать животных в файл с именем animals.out, а фрукты — в другой файл с именем fruits.out.

Вот как это можно сделать, используя два оператора open в одном выражении with:

items = ['dog', 'cat', 'apple', 'pear', 'lion', 'banana']

with open('animals.out', 'w') as animals_f, open('fruits.out', 'w') as fruits_f:
    for item in items:
        if item in ['dog', 'cat', 'lion']:
            animals_f.write(item+'\n')

        if item in ['apple', 'pear', 'banana']:
            fruits_f.write(item+'\n')

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

$ python with_open_example.py 
$ cat fruits.out
apple
pear
banana
$ cat animals.out
dog
cat
lion

Для использования двух открытых операторов в одном выражении требуется Python 2.7, Python 3.1 или более новая версия.

Использование вложенных операторов with open в Python

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

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

items = ['dog', 'cat', 'apple', 'pear', 'lion', 'banana']

with open('animals.out', 'w') as animals_f:
    with open('fruits.out', 'w') as fruits_f:
        for item in items:
            if item in ['dog', 'cat', 'lion']:
                animals_f.write(item+'\n')

            if item in ['apple', 'pear', 'banana']:
                fruits_f.write(item+'\n')

Ниже вы можете видеть, что программа по-прежнему делает то, что должна делать 🙂

$ python with_open_example.py 
$ cat fruits.out 
apple
pear
banana
$ cat animals.out 
dog
cat
lion

Использование Python с open для работы с бинарными файлами

Мы часто работаем с текстовыми файлами, но как насчет двоичных файлов?

Например, как бы вы открыли файл PNG, используя то, что мы узнали об операторе with?

В текущем каталоге я загрузил картинку под названием python.png:

$ ls -ltr
total 208
-rw-r--r--@ 1 myuser  mygroup  102916 22 Feb 20:13 python.png

Из вывода команды ls выше мы уже знаем, что его размер составляет 102916 байт.

Давайте откроем его и проверим его размер в Python.

Как получить количество байтов в файле с помощью Python?

with open('python.png', 'rb') as png_file:
    bytes_count = 0

    while png_file.read(1):
        bytes_count += 1

print("The size of the file is: {}".format(bytes_count))

Вот что мы сделали в нашем коде:

  1. Используем with open … as для открытия файла PNG в двоичном режиме.
  2. Считываем по одному байту, используя цикл while, пока не достигнем конца файла.
  3. Увеличиваем значение целого числа bytes_count каждый раз, когда мы считываем байт.

Результат работы программы:

$ python read_binary_file.py
The size of the file is: 102916

Размер файла, рассчитанный нашей программой, совпадает с размером, показанным командой ls. Отлично!

Использование Try Finally как эквивалента with open … as

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

Мы будем использовать оператор try … finally, чтобы убедиться, что объект файла всегда закрыт после выполнения блока кода try. Я хочу написать что-то похожее на следующее:

>>> with open('output.txt') as f:
...     data = f.read()

Вот код:

>>> f = open('output.txt')
>>> try:
...     data = f.read()
... finally:
...     f.close()
... 
>>> f.closed
True

Видите ли вы преимущество использования with open вместо этого?

Это определенно делает наш код более лаконичным. Представьте, если бы нам пришлось использовать операторы try … finally для каждого открываемого файла!

Заключение

В этом простом руководстве мы увидели, как использовать команду open в Python для упрощения работы с файлами.

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

Автор

Фото аватара

Владимир Михайлов

Программист на Python с большим количеством опыта и разнообразных проектов.