Основы работы с файлами в Python
Введение в работу с файлами в Python с помощью встроенной функциональности языка.
Михаил Свинцов
автор курса «Full-stack веб-разработчик на Python»
Взаимодействие с файловой системой позволяет хранить информацию, полученную в результате работы программы. Михаил Свинцов из SkillFactory расскажет о базовой функциональности языка программирования Python для работы с файлами.
Встроенные средства Python
Основа для работы с файлами — built-in функция open()
open(file, mode="rt")
Эта функция имеет два аргумента. Аргумент file принимает строку, в которой содержится путь к файлу. Второй аргумент, mode , позволяет указать режим, в котором необходимо работать с файлом. По умолчанию этот аргумент принимает значение «rt», с которым, и с некоторыми другими, можно ознакомиться в таблице ниже
Эти режимы могут быть скомбинированы. Например, «rb» открывает двоичный файл для чтения. Комбинируя «r+» или «w+» можно добиться открытия файла в режиме и чтения, и записи одновременно с одним отличием — первый режим вызовет исключение, если файла не существует, а работа во втором режиме в таком случае создаст его.
Начать саму работу с файлом можно с помощью объекта класса io.TextIOWrapper , который возвращается функцией open() . У этого объекта есть несколько атрибутов, через которые можно получить информацию
- name — название файла;
- mode — режим, в котором этот файл открыт;
- closed — возвращает True , если файл был закрыт.
По завершении работы с файлом его необходимо закрыть при помощи метода close()
f = open("examp.le", "w") // работа с файлом f.close()
Однако более pythonic way стиль работы с файлом встроенными средствами заключается в использовании конструкции with .. as .. , которая работает как менеджер создания контекста. Написанный выше пример можно переписать с ее помощью
with open("examp.le", "w") as f: // работа с файлом
Главное отличие заключается в том, что python самостоятельно закрывает файл, и разработчику нет необходимости помнить об этом. И бонусом к этому не будут вызваны исключения при открытии файла (например, если файл не существует).
Чтение из файла
При открытии файла в режимах, допускающих чтение, можно использовать несколько подходов.
Для начала можно прочитать файл целиком и все данные, находящиеся в нем, записать в одну строку.
with open("examp.le", "r") as f: text = f.read()
Используя эту функцию с целочисленным аргументом, можно прочитать определенное количество символов.
with open("examp.le", "r") as f: part = f.read(16)
При этом будут получены только первые 16 символов текста. Важно понимать, что при применении этой функции несколько раз подряд будет считываться часть за частью этого текста — виртуальный курсор будет сдвигаться на считанную часть текста. Его можно сдвинуть на определенную позицию, при необходимости воспользовавшись методом seek() .
with open("examp.le", "r") as f: # 'Hello, world!' first_part = f.read(8) # 'Hello, w' f.seek(4) second_part = f.read(8) # 'o, world'
Другой способ заключается в считывании файла построчно. Метод readline() считывает строку и, также как и с методом read() , сдвигает курсор — только теперь уже на целую строку. Применение этого метода несколько раз будет приводить к считыванию нескольких строк. Схожий с этим способом, другой метод позволяет прочитать файл целиком, но по строкам, записав их в список. Этот список можно использовать, например, в качестве итерируемого объекта в цикле.
with open("examp.le", "r") as f: for line in f.readlines(): print(line)
Однако и здесь существует более pythonic way. Он заключается в том, что сам объект io.TextIOWrapper имеет итератор, возвращающий строку за строкой. Благодаря этому нет необходимости считывать файл целиком, сохраняя его в список, а можно динамически по строкам считывать файл. И делать это лаконично.
with open("examp.le", "r") as f: for line in f: print(line)
Запись в файл
Функциональность внесения данных в файл не зависит от режима — добавление данных или перезаписывание файла. В выполнении этой операции также существует несколько подходов.
Самый простой и логичный — использование функции write()
with open("examp.le", "w") as f: f.write(some_string_data)
Важно, что в качестве аргумента функции могут быть переданы только строки. Если необходимо записать другого рода информацию, то ее необходимо явно привести к строковому типу, используя методы __str__(self) для объектов или форматированные строки.
Есть возможность записать в файл большой объем данных, если он может быть представлен в виде списка строк.
with open("examp.le", "w") as f: f.writelines(list_of_strings)
Здесь есть еще один нюанс, связанный с тем, что функции write() и writelines() автоматически не ставят символ переноса строки, и это разработчику нужно контролировать самостоятельно.
Существует еще один, менее известный, способ, но, возможно, самый удобный из представленных. И как бы не было странно, он заключается в использовании функции print() . Сначала это утверждение может показаться странным, потому что общеизвестно, что с помощью нее происходит вывод в консоль. И это правда. Но если передать в необязательный аргумент file объект типа io.TextIOWrapper , каким и является объект файла, с которым мы работаем, то поток вывода функции print() перенаправляется из консоли в файл.
with open("examp.le", "w") as f: print(some_data, file=f)
Сила такого подхода заключается в том, что в print() можно передавать не обязательно строковые аргументы — при необходимости функция сама их преобразует к строковому типу.
На этом знакомство с базовой функциональностью работы с файлами можно закончить. Вместе с этим стоит сказать, что возможности языка Python им не ограничивается. Существует большое количество библиотек, которые позволяют работать с файлами определенных типов, а также допускают более тесное взаимодействие с файловой системой. И в совокупности они предоставляют разработчикам легкий и комфортный способ работы с файлами.
Чтение данных из файла и запись в файл
В Python, чтобы создать файл, надо его открыть в режиме записи ( ‘w’ , ‘wb’ ) или дозаписи ( ‘a’ , ‘ab’ ).
f2 = open("text2.txt", 'w')
Функция open() возвращает файловый объект.
Без ‘b’ создается текстовый файл, представляющий собой поток символов. С ‘b’ — файл, содержащий поток байтов.
В Python также существует режим ‘x’ или ‘xb’ . В этом режиме проверяется, есть ли файл. Если файл с определенным именем уже существует, он не будет создан. В режиме ‘w’ файл создается заново, старый при этом теряется.
>>> f1 = open('text1.txt', 'w') >>> f2 = open('text1.txt', 'x') Traceback (most recent call last): File "", line 1, in FileExistsError: [Errno 17] File exists: 'text1.txt' >>> f3 = open('text1.txt', 'w')
Чтение данных из файла
Если в функцию open() не передается второй аргумент, файл расценивается как текстовый и открывается на чтение.
Попытка открыть на чтение несуществующий файл вызывает ошибку.
>>> f = open("text10.txt") Traceback (most recent call last): File "", line 1, in IOError: [Errno 2] No such file or directory: 'text10.txt'
Перехватить возникшее исключение можно с помощью конструкции try-except .
>>> try: . f = open("text10.txt") . except IOError: . print ("No file") . No file
Получить все данные из файла можно с помощью метода read() файлового объекта, предварительно открыв файл на чтение. При этом файловый объект изменяется и получить из него данные еще раз не получится.
>>> f = open("text.txt") >>> f >>> fd = f.read() >>> fd1 = f.read() >>> fd 'Hello\n\tOne\n Two\nThree Four\nШесть!\n' >>> fd1 ''
Если файл был открыт в текстовом режиме, то метод read() возвращает строку. В случае бинарного режима возвращается объект типа bytes .
>>> f = open('text.txt', 'rb') >>> content = f.read() >>> type(content) >>> content b'HelloHello' >>> content[0] 72 >>> chr(content[0]) 'H'
Методу read() может быть передан один аргумент, обозначающий количество символов (если файл был открыт как текстовый) или байт (если файл был открыт как бинарный) для чтения.
>>> f = open("text.txt") >>> fd = f.read(10) >>> fd1 = f.read(5) >>> fd 'Hello\n\tOne' >>> fd1 '\n T'
Метод readline() позволяет получать данные построчно.
>>> f = open("text.txt") >>> f.readline() 'Hello\n' >>> f.readline() '\tOne\n' >>> f.readline() ' Two\n'
Принимает аргумент — число байт или символов.
>>> f.readline(3) 'Thr' >>> f.readline(3) 'ee ' >>> f.readline(3) 'Fou' >>> f.readline(3) 'r\n' >>> f.readline(5) 'Шесть' >>> f.readline(5) '!\n'
Для построчного чтения данных из файла рекомендуется использовать цикл for :
>>> f = open('text.txt') >>> for line in f: . print(line, end='') . Hello! The second line. >>> f.close()
Метод readlines() считывает все строки и помещает их в список.
>>> f = open("text.txt") >>> fd = f.readlines() >>> fd ['Hello\n', '\tOne\n', ' Two\n', 'Three Four\n', 'Шесть!\n']
Может принимать количество символов, но дочитывает строку до конца.
>>> f = open("text.txt") >>> fd = f.readlines(3) >>> fd ['Hello\n'] >>> fd1 = f.readlines(6) >>> fd1 ['\tOne\n', ' Two\n']
Запись данных в файл
Записать данные в файл можно с помощью метода write() , который возвращает число записанных символов или байтов.
>>> ft = open('text1.txt', 'w') >>> fb = open('text2.txt', 'wb') >>> t = 'Привет Мир!' >>> b = b'Hello World!' >>> type(t), type(b) (, ) >>> ft.write(t) 11 >>> fb.write(b) 12 >>> ft.close() >>> fb.close() >>> >>> import os.path >>> os.path.getsize('text1.txt') 20 >>> os.path.getsize('text2.txt') 12 >>> open('text2.txt').read() 'Hello World!'
Если записываемые в текстовый файл данные не являются строкой, то их предварительно надо преобразовать в строку.
>>> a = [1, 2, 3, 4] >>> sa = str(a) >>> sa '[1, 2, 3, 4]' >>> f = open('mylist.txt', 'w') >>> f.write(sa) 12 >>> f.close() >>> >>> with open('mylist.txt') as f: . sa = f.read() . >>> sa '[1, 2, 3, 4]' >>> list(sa) # bad idea ['[', '1', ',', ' ', '2', ',', ' ', '3', ',', ' ', '4', ']'] >>> a = [int(i) for i in sa if i.isdigit()] >>> a [1, 2, 3, 4]
С помощью метода writelines() можно записать в файл итерируемую последовательность.
>>> a = [1,2,3,4,5,6,7,8,9,0] >>> f = open("text2.txt",'w') >>> f.writelines("%s\n" % i for i in a) >>> f.close() >>> open("text2.txt").read() '1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n' >>> print(open("text2.txt").read()) 1 2 3 4 5 6 7 8 9 0
Смена позиции в файле
Метод tell() возвращает текущую позицию в файле. Позицию можно менять с помощью метода seek() .
>>> f = open('text.txt') >>> f.tell() 0 >>> f.readline() 'Hello!\n' >>> f.tell() 7 >>> f.seek(5) 5 >>> f.read(1) '!' >>> f.tell() 6 >>> f.read() '\nThe second line.\n' >>> f.read() '' >>> f.seek(0) 0 >>> f.read() 'Hello!\nThe second line.\n'
В случае бинарных файлов в метод seek() можно передавать второй аргумент, который указывает, с какого места выполняется смещение, указанное в первом аргументе: 0 (по умолчанию) — от начала файла, 1 — с текущей позиции, 2 — с конца.
>>> f = open('text.txt', 'rb') >>> f.read() b'Hello!\nThe second line.\n' >>> f.seek(-6, 2) 18 >>> f.read(4) b'line' >>> f.seek(0) 0 >>> f.read(5) b'Hello' >>> f.seek(2, 1) 7 >>> f.read(3) b'The'
Закрытие файла
В Python следует закрывать файл для высвобождения системных ресурсов. Делается это с помощью метода close() файлового объекта.
С помощью closed (не константа, а так называемый дескриптор, или описатель, данных) проверяют, закрыт файл или нет.
>>> f = open('text.txt') >>> f.closed False >>> f.close() >>> f.closed True
Считается хорошей практикой использовать оператор with при обработке файловых объектов. После того как тело with завершит работу, файл автоматически будет закрыт. При работе with создается так называемый контекстный менеджер, представляющий собой особый объект. Благодаря ему сохраняются и восстанавливаются глобальные состояния, происходит блокировка и разблокировка ресурсов, закрываются открытые файлы и др.
>>> with open('text.txt') as f: . print(f.read()) . HelloHello >>> f.closed True
>>> with open('text.txt') as fr, open('text2.txt', 'w') as fw: . fw.write(fr.read()) . 10 >>> fw.closed True
>>> with ( . open('text.txt') as fr, . open('text2.txt', 'w') as fw, . ): . fw.write(fr.read()) . 10
Двоичные файлы
Пример копирования изображения:
>>> f1 = open('flag.png', 'rb') >>> f2 = open('flag2.png', 'wb') >>> f2.write(f1.read()) 446 >>> f1.close() >>> f2.close()
Модуль struct позволяет преобразовывать данные к бинарному виду и обратно.
>>> f = open('text3.txt', 'wb') >>> f.write('3') Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface >>> d = struct.pack('>i',3) >>> d b'\x00\x00\x00\x03' >>> f.write(d) 4 >>> f.close() >>> f = open('text3.txt') >>> d = f.read() >>> d '\x00\x00\x00\x03' >>> struct.unpack('>i',d) Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface >>> f = open('text3.txt', 'rb') >>> d = f.read() >>> d b'\x00\x00\x00\x03' >>> struct.unpack('>i',d) (3,)
Файлы в python, ввод-вывод
Эта статья посвящена работе с файлами (вводу/выводу) в Python: открытие, чтение, запись, закрытие и другие операции.
Файлы Python
Файл — это всего лишь набор данных, сохраненный в виде последовательности битов на компьютере. Информация хранится в куче данных (структура данных) и имеет название «имя файла» (filename).
В Python существует два типа файлов:
Текстовые файлы
Это файлы с человекочитаемым содержимым. В них хранятся последовательности символов, которые понимает человек. Блокнот и другие стандартные редакторы умеют читать и редактировать этот тип файлов.
Текст может храниться в двух форматах: ( .txt ) — простой текст и ( .rtf ) — «формат обогащенного текста».
Бинарные файлы
В бинарных файлах данные отображаются в закодированной форме (с использованием только нулей (0) и единиц (1) вместо простых символов). В большинстве случаев это просто последовательности битов.
Они хранятся в формате .bin .
Любую операцию с файлом можно разбить на три крупных этапа:
- Открытие файла
- Выполнение операции (запись, чтение)
- Закрытие файла
Открытие файла
Метод open()
В Python есть встроенная функция open() . С ее помощью можно открыть любой файл на компьютере. Технически Python создает на его основе объект.
f = open(file_name, access_mode)
- file_name = имя открываемого файла
- access_mode = режим открытия файла. Он может быть: для чтения, записи и т. д. По умолчанию используется режим чтения ( r ), если другое не указано. Далее полный список режимов открытия файла
| Режим | Описание |
|---|---|
| r | Только для чтения. |
| w | Только для записи. Создаст новый файл, если не найдет с указанным именем. |
| rb | Только для чтения (бинарный). |
| wb | Только для записи (бинарный). Создаст новый файл, если не найдет с указанным именем. |
| r+ | Для чтения и записи. |
| rb+ | Для чтения и записи (бинарный). |
| w+ | Для чтения и записи. Создаст новый файл для записи, если не найдет с указанным именем. |
| wb+ | Для чтения и записи (бинарный). Создаст новый файл для записи, если не найдет с указанным именем. |
| a | Откроет для добавления нового содержимого. Создаст новый файл для записи, если не найдет с указанным именем. |
| a+ | Откроет для добавления нового содержимого. Создаст новый файл для чтения записи, если не найдет с указанным именем. |
| ab | Откроет для добавления нового содержимого (бинарный). Создаст новый файл для записи, если не найдет с указанным именем. |
| ab+ | Откроет для добавления нового содержимого (бинарный). Создаст новый файл для чтения записи, если не найдет с указанным именем. |
Пример
Создадим текстовый файл example.txt и сохраним его в рабочей директории.

Следующий код используется для его открытия.
f = open('example.txt','r') # открыть файл из рабочей директории в режиме чтения fp = open('C:/xyz.txt','r') # открыть файл из любого каталога
В этом примере f — переменная-указатель на файл example.txt .
Следующий код используется для вывода содержимого файла и информации о нем.
>>> print(*f) # выводим содержимое файла This is a text file. >>> print(f) # выводим объект _io.TextIOWrapper name='example.txt' mode='r' encoding='cp1252'>
Стоит обратить внимание, что в Windows стандартной кодировкой является cp1252 , а в Linux — utf-08 .
Закрытие файла
Метод close()
После открытия файла в Python его нужно закрыть. Таким образом освобождаются ресурсы и убирается мусор. Python автоматически закрывает файл, когда объект присваивается другому файлу.
Существуют следующие способы:
Способ №1
Проще всего после открытия файла закрыть его, используя метод close() .
f = open('example.txt','r') # работа с файлом f.close()
После закрытия этот файл нельзя будет использовать до тех пор, пока заново его не открыть.
Способ №2
Также можно написать try/finally , которое гарантирует, что если после открытия файла операции с ним приводят к исключениям, он закроется автоматически.
Без него программа завершается некорректно.
Вот как сделать это исключение:
f = open('example.txt','r') try: # работа с файлом finally: f.close()
Файл нужно открыть до инструкции try , потому что если инструкция open сама по себе вызовет ошибку, то файл не будет открываться для последующего закрытия.
Этот метод гарантирует, что если операции над файлом вызовут исключения, то он закроется до того как программа остановится.
Способ №3
Инструкция with
Еще один подход — использовать инструкцию with , которая упрощает обработку исключений с помощью инкапсуляции начальных операций, а также задач по закрытию и очистке.
В таком случае инструкция close не нужна, потому что with автоматически закроет файл.
Вот как это реализовать в коде.
with open('example.txt') as f: # работа с файлом
Чтение и запись файлов в Python
В Python файлы можно читать или записывать информацию в них с помощью соответствующих режимов.
Функция read()
Функция read() используется для чтения содержимого файла после открытия его в режиме чтения ( r ).
Синтаксис
file.read(size)
- file = объект файла
- size = количество символов, которые нужно прочитать. Если не указать, то файл прочитается целиком.
Пример
>>> f = open('example.txt','r') >>> f.read(7) # чтение 7 символов из example.txt 'This is '
Интерпретатор прочитал 7 символов файла и если снова использовать функцию read() , то чтение начнется с 8-го символа.
>>> f.read(7) # чтение следующих 7 символов ' a text'
Функция readline()
Функция readline() используется для построчного чтения содержимого файла. Она используется для крупных файлов. С ее помощью можно получать доступ к любой строке в любой момент.
Пример
Создадим файл test.txt с нескольким строками:
This is line1. This is line2. This is line3.
Посмотрим, как функция readline() работает в test.txt .
>>> x = open('test.txt','r') >>> x.readline() # прочитать первую строку This is line1. >>> x.readline(2) # прочитать вторую строку This is line2. >>> x.readlines() # прочитать все строки ['This is line1.','This is line2.','This is line3.']
Обратите внимание, как в последнем случае строки отделены друг от друга.
Функция write()
Функция write() используется для записи в файлы Python, открытые в режиме записи.
Если пытаться открыть файл, которого не существует, в этом режиме, тогда будет создан новый.
Синтаксис
file.write(string)
Пример
Предположим, файла xyz.txt не существует. Он будет создан при попытке открыть его в режиме чтения.
>>> f = open('xyz.txt','w') # открытие в режиме записи >>> f.write('Hello \n World') # запись Hello World в файл Hello World >>> f.close() # закрытие файла
Переименование файлов в Python
Функция rename()
Функция rename() используется для переименовывания файлов в Python. Для ее использования сперва нужно импортировать модуль os.
import os os.rename(src,dest)
- src = файл, который нужно переименовать
- dest = новое имя файла
Пример
>>> import os >>> # переименование xyz.txt в abc.txt >>> os.rename("xyz.txt","abc.txt")
Текущая позиция в файлах Python
В Python возможно узнать текущую позицию в файле с помощью функции tell() . Таким же образом можно изменить текущую позицию командой seek() .
Пример
>>> f = open('example.txt') # example.txt, который мы создали ранее >>> f.read(4) # давайте сначала перейдем к 4-й позиции This >>> f.tell() # возвращает текущую позицию 4 >>> f.seek(0,0) # вернем положение на 0 снова
Методы файла в Python
| file.close() | закрывает открытый файл |
| file.fileno() | возвращает целочисленный дескриптор файла |
| file.flush() | очищает внутренний буфер |
| file.isatty() | возвращает True, если файл привязан к терминалу |
| file.next() | возвращает следующую строку файла |
| file.read(n) | чтение первых n символов файла |
| file.readline() | читает одну строчку строки или файла |
| file.readlines() | читает и возвращает список всех строк в файле |
| file.seek(offset[,whene]) | устанавливает текущую позицию в файле |
| file.seekable() | проверяет, поддерживает ли файл случайный доступ. Возвращает True , если да |
| file.tell() | возвращает текущую позицию в файле |
| file.truncate(n) | уменьшает размер файл. Если n указала, то файл обрезается до n байт, если нет — до текущей позиции |
| file.write(str) | добавляет строку str в файл |
| file.writelines(sequence) | добавляет последовательность строк в файл |
Работа с файлами
Для открытия файлов в python используется функция open :
file = open("/path/for/your/file.txt", "r")
Она возвращает поток — интерфейс взаимодействия с содержимым файла.
Функция open принимает первым аргументом полное имя файла (с путём, абсолютным или относительным), вторым — режим, в котором мы откроем файл
| Режим | Обозначение |
|---|---|
| ‘r’ | открытие на чтение (является значением по умолчанию). |
| ‘w’ | открытие на запись, содержимое файла удаляется, если файла не существует, создается новый. |
| ‘x’ | открытие на запись, если файла не существует, иначе исключение. |
| ‘a’ | открытие на дозапись, информация добавляется в конец файла. |
| ‘b’ | открытие в двоичном режиме. |
| ‘t’ | открытие в текстовом режиме (является значением по умолчанию). |
| ‘+’ | открытие на чтение и запись |
По умолчанию файл открывается в режиме rt — для чтения в текстовом формате.
Стоит заметить, что файл можно открыть в двух разных форматах: текстовом и бинарном (двоичном). Файлы, открытые в текстовом формате (по умолчанию, или явно добавляя “t” к аргументу режима), обрабатываются Python-ом и возвращаются как строки. При открытии файла в бинарном формате никакой обработки содержимого не производится, содержимое возвращается побайтово.
Таким образом, если мы хотим открыть файл в двоичном формате для записи, надо использовать режим “wb”, если мы хотим дописать содержимое в конец файла в текстовом формате, то — “a” или “at”, “r+b” — открыть двоичный файл на чтение и запись.
Обычно, файлы, в которых содержится текст, например, файлы txt , код вашей программы, файлы формата csv , открываются в текстовом формате, а файлы, которые нельзя проинтерпретировать как текст — в бинарном (например, картинки, музыку). Иногда файлы с текстом открывают в бинарном режиме, для более явного управления всеми спецсимволами (например табуляция ↹).
При открытии файла в текстовом режиме, также можно указать подходящую кодировку. Например, если в вашем файле содержится текст на русском в utf8, откройте его в этой кодировке:
russian_file = open("russian.txt", "r", encoding="utf8")
Как только файл был открыт и у вас появился файловый объект, вы можете получить следующую информацию о нем:
| Атрибут | Значение |
|---|---|
| file.closed | Возвращает True если файл был закрыт. |
| file.mode | Возвращает режим доступа, с которым был открыт файл. |
| file.name | Возвращает имя файла. |
У получаемого объекта есть несколько полезных методов, рассмотрим их.
-
метод read ( n ) позволяет прочитать следующие n символов файла. Замечу, что можно представить, что в нашем объекте файла есть указатель на текущую читаемую позицию. При открытии файла, она ставится в самое начало. По мере чтения, этот указатель сдвигается. Таким образом, если выполнять read ( n ) несколько раз подряд, мы будем получать не первые n символов, а каждый раз новые, n символов.
Если n явно не указать, то считается весь файл целиком (указатель окажется в самом конце файла). Для использования метода read, файл должен быть открыт в режиме для чтения Примечание: чтобы узнать текущее положение указателя внутри файла, можно воспользоваться методом tell () , а чтобы установить указатель в нужное положение pos , используется метод seek ( pos )
file = open("russian.txt", "r", encoding="utf8") #открыли файл, file.tell() == 0, #т.е указатель стоит в самом начале text = file.read() #считали весь файл
Следует сказать, что открытый в любом режиме файл после его использования нужно обязательно закрывать. Делается это методом close(). Посе его выполнения работа с файлом будет корректно завершена, но с нашим объектом файла работать уже тоже будет нельзя — при необходимости повторной работы с файлом нужно снова его открывать при помощи open.
file = open("some_data.txt") text = file.read() file.close() #дальше работаем с text, если надо
Но вдруг в процессе выполнения нашей программы произройдет критическая ошибка и программа завершит свое выполнение, а мы, например, записывали в файл какую-то информацию? Верно, вполне возможно, что последняя добавленная информация в файл так и не запишется. Чтобы избежать такой ситуации, ну и чтобы просто не забывать вовремя вызывать close() используется конструкция with:
with open("text.txt", "w") as out: #в out теперь находится ссылка на наш объект файла, как если #бы было просто out = open("text.txt", "w") for i in range(100): out.write("А я запишу все эти строки в влюбом случае\n") #записываем 100 одинаковых строчек raise Exception #принудительно "вызываем" ошибку. #Об Exceptionах будет дальше в следующих семинарах #в файле все равно будут все 100 нужные строки
Конструкция with используется для того, чтобы гаранировать, что критические действия будут выполнены в любом случае, ее можно использовать и в некоторых других случаях, но в контексте открытия файлов она используется чаще всего.
Я рекомендую по возможности всегда открывать файлы, не зависимо от режима, с конструкцией with!
Через конструкцию with можно открывать сразу несколько файлов:
with open("input.txt", "r") as input, open("output.txt", "w") as output: output.write(input.read()) #скопировали содержимое input в output
- Чтобы считать из файла целую строку, используется метод readline(max_len). Если указать параметр max_len, то будут считаны максимум max_len символов
with open("text.txt", "r") as file: print(file.readline()) #считали и вывели первую строку файла
На самом деле у нашего объекта файла есть итератор, поэтому перебирать строки внутри файла можно с его помощью:
with open("text.txt", "r") as file: for line in file: print(line)
Такой способ чтения наиболее удобен для построчного чтения
Упражнение 1: создайте произвольный текстовый файл с несколькими строками произвольного текста. Выведите в консоль строки файла, удалив лишние пробелы в начале и конце строк, если они есть
Упражнение 2: запишите в новый файл содержимое списка строк (каждую строку с новой строки) без использования цикла
def write_array(array, file_name): """записывает строки из array в файл file_name""" #ваш код здесь pass
Работа с файловой системой
Взаимодействие с файлами не ограничивается только самими файлами, нам часто приходится работать и с папками. Главными героями этого раздела будут библиотеки os и os.path. Они связаны с операционной системой компьютера и позволяют взаимодейстовать с файловой системой.
Все папки директории
os.listdir(dir) перечисялет файлы и папки в указанной директории dir. Если вызвать эту функцию без аргументов, она вернет файлы и папки текущей рабочей директории.
Текущая папка
Относительные пути строятся относительно текущей папки. Чтобы получить абсолютный путь файла из относительного, используется функция os.path.abspath(file_path). Чтобы узнать, какая папка является текущей, можно вызвать функцию os.getcwd(). Для смены текущей папки используется os.chdir(new_dir).
Проверка существования файла или папки и определение, является ли имя файлом или папкой
os.path.exists(file_name) проверяет, существует ли указанный файл (или директория) file_name.
Чтобы проверить, является ли данное имя name файлом или папкой, можно воспользоваться функциями os.isdir(name) или os.isfile(name), которые возвращают True или False.
Рекурсивный обход папок
Одной из самых интересных и мощных функций является функция os.walk(dir) — она позволяет рекурсивно пройтись по всем папкам, подпапкам, их подпапкам и так далее. На самом деле она возвращает генератор (последовательность элементов). Каждый элемент представляеьт собой кортеж из 3х элементов. Первый элемнт — строковое представление директории текущей директории, которую просматривает функция. Вторым элементом — список всех подпапок данной директории, а третьим — список всех файлов этой директории.
for current_dir, dirs, files in os.walk("."): #передаем в качестве аргумента текущую директорию #("." - означает именно ее) print(current_dir, dirs, files) #выведем, что получается
Копирование файлов
Копировать файлы можно при помощи функции copy из модуля shutil
shutil.copy("input.txt", "output.txt")
Копировать папки можно с помощью copytree из того же модуля:
shutil.copytree("test", "test/test2") #Скопирует папку test внутрь неё самой же в подпапку test2
Многие другие функции для работы с файлами и папками вы сможете найти в модулях os и shutil. Теперь вы знаете, где искать нужный функционал 😉
Упражнение 3: Вам дана в архиве файловая структура, состоящая из директорий и файлов.
Вам необходимо распаковать этот архив (средствами языка python), и затем найти в данной в файловой структуре все директории, в которых есть хотя бы один файл с расширением “.py”.
Ответом на данную задачу будет являться файл со списком таких директорий, отсортированных в лексикографическом порядке.
Распространенные форматы текстовых данных
csv
csv является табличным форматом. В нем содержатся значения разделенные запятой (Comma-Separated Values). Например,
first name,last name,module1,module2,module3 Nikolay,Neznaev,0,20,10 Stepan,Sharyashiy,100,99.5,100
Для работы с csv файлами можно воспользоваться библиотекой csv:
import csv with open("example.csv", "r") as file: reader = csv.reader(file) #На основе открытого файла получаем объект из библиотеки csv for row in reader: print(row) #Каждая строка - список значений
В csv.reader параметром delimeter можно передать разделитель значений, таким образом разделяющим символом в файле csv может быть не только запятая.
Для изолирования некоторых значений можно пользоваться двойными кавычками. Библиотека csv учитывает различные мелочи, такие как строки с содержащимися в ней запятыми и переносами строки, различные разделители, поэтому ее использование целесообразнее splitа по разделителю.
Для записи значений в csv формате используется csv.writer:
import csv students = [ ["Greg", "Lebovskiy", 70, 80, 90, "Good job, Greg!"], ["Nick", "Shalopaev", 10, 50, 45, "Shalopaev, you should study better!"] ] with open("example.csv", "a") as file: writer = csv.writer(file) #На основе открытого файла получаем объект из библиотеки csv for student in students: writer.writerow(student) #Записываем строку #Вместо цикла выше мы могли сразу записать все через writer.writerows(students)
JSON
JSON (JavaScript Object Notation) — простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. Впервые он был придуман и использован в JavaScript для хранения структур и классов, но быстро обео свою популярность и вышел за пределы своего родителя.
JSON основан на двух структурах данных: * Коллекция пар ключ/значение. В разных языках, эта концепция реализована как объект, запись, структура, словарь, хэш, именованный список или ассоциативный массив. * Упорядоченный список значений. В большинстве языков это реализовано как массив, вектор, список или последовательность.
Это универсальные структуры данных. Почти все современные языки программирования поддерживают их в какой-либо форме. Логично предположить, что формат данных, независимый от языка программирования, должен быть основан на этих структурах.
Объекты в формате SJON хранятся как словари в Python, но с некоторыми деталями: во первых, ключом в json-объекте может быть только строка, значения True и False пишутся с маленькой буквы, значению None соответствует значение null, строки хранятся только внутри двойных кавычек.
Для удобной работы с json файлами в языке python можно использовать библиотеку json
import json student1 = "full_name" : "Greg Martin", "scores" : [100, 85, 94], "certificate" : True, "comment": "Great job, Greg!" > student2 = "full_name" : "John Price", "scores" : [0, 10, 0], "certificate" : False, "comment": "Guns aren't gonna help you here, captain!" > data = [student1, student2] print(json.dumps(data, indent=4, sort_keys=True)) #Делаем отступы в 4 пробела, сортируем ключи в алфавитном порядке
Для получения строкового представления объекта в формате json можно использовать json.dumps(data, **parrams) с различными вспомогательными настройками (пробелы, сортировка и др.)
Для записи в файл можно воспользоваться json.dump(data, file_obj, **params):
with open("output.json", "w") as out: json.dump(data, out, indent=4, sort_keys=True)
Для получения объекта python на основе его срокового представления можно воспользоваться функцией json.loads или json.load для считывания из файла:
json_str = json.dumps(data, indent=4, sort_keys=True) #получение строкового представления json data_again = json.loads(json_str) #получаем объект python print(sum(data_again[0]["scores"])) #убедимся в кореектном считывании: #посчитаем сумму баллов у первого студента with open("output.json") as file: data_from_file = json.load(file) #считаем объект из файла print(sum(data_from_file[0]["scores"])) #аналогично посчитаем сумму баллов
При записи-считывнии объектов из формата json кортежи превращаются в списки # Исключения (материал ниже взят с сайта https://pythonworld.ru/tipy-dannyx-v-python/isklyucheniya-v-python-konstrukciya-try-except-dlya-obrabotki-isklyuchenij.html )
Исключения (exceptions) — ещё один тип данных в python. Исключения необходимы для того, чтобы сообщать программисту об ошибках.
Самый простейший пример исключения — деление на ноль:
100 / 0 Traceback (most recent call last): File "", line 1, in 100 / 0 ZeroDivisionError: division by zero
Разберём это сообщение подробнее: интерпретатор нам сообщает о том, что он поймал исключение и напечатал информацию (Traceback (most recent call last)).
Далее имя файла (File «»). Имя пустое, потому что мы находимся в интерактивном режиме, строка в файле (line 1);
Выражение, в котором произошла ошибка (100 / 0).
Название исключения (ZeroDivisionError) и краткое описание исключения (division by zero).
Разумеется, возможны и другие исключения:
2 + '1' Traceback (most recent call last): File "", line 1, in 2 + '1' TypeError: unsupported operand type(s) for +: 'int' and 'str' int('qwerty') Traceback (most recent call last): File "", line 1, in int('qwerty') ValueError: invalid literal for int() with base 10: 'qwerty'
В этих двух примерах генерируются исключения TypeError и ValueError соответственно. Подсказки дают нам полную информацию о том, где порождено исключение, и с чем оно связано.
Рассмотрим иерархию встроенных в python исключений, хотя иногда вам могут встретиться и другие, так как программисты могут создавать собственные исключения. Данный список актуален для python 3.3, в более ранних версиях есть незначительные изменения.
- BaseException — базовое исключение, от которого берут начало все остальные.
- SystemExit — исключение, порождаемое функцией sys.exit при выходе из программы.
- KeyboardInterrupt — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
- GeneratorExit — порождается при вызове метода close объекта generator.
- Exception — а вот тут уже заканчиваются полностью системные исключения (которые лучше не трогать) и начинаются обыкновенные, с которыми можно работать.
- StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов.
- ArithmeticError — арифметическая ошибка.
- FloatingPointError — порождается при неудачном выполнении операции с плавающей запятой. На практике встречается нечасто.
- OverflowError — возникает, когда результат арифметической операции слишком велик для представления. Не появляется при обычной работе с целыми числами (так как python поддерживает длинные числа), но может возникать в некоторых других случаях.
- ZeroDivisionError — деление на ноль.
- IndexError — индекс не входит в диапазон элементов.
- KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
- UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
- BlockingIOError
- ChildProcessError — неудача при операции с дочерним процессом.
- ConnectionError — базовый класс для исключений, связанных с подключениями.
- BrokenPipeError
- ConnectionAbortedError
- ConnectionRefusedError
- ConnectionResetError
- IndentationError — неправильные отступы.
- TabError — смешивание в отступах табуляции и пробелов.
- UnicodeEncodeError — исключение, связанное с кодированием unicode.
- UnicodeDecodeError — исключение, связанное с декодированием unicode.
- UnicodeTranslateError — исключение, связанное с переводом unicode.
Теперь, зная, когда и при каких обстоятельствах могут возникнуть исключения, мы можем их обрабатывать. Для обработки исключений используется конструкция try — except.
Первый пример применения этой конструкции:
try: k = 1 / 0 except ZeroDivisionError: k = 0 print(k)
В блоке try мы выполняем инструкцию, которая может породить исключение, а в блоке except мы перехватываем их. При этом перехватываются как само исключение, так и его потомки. Например, перехватывая ArithmeticError, мы также перехватываем FloatingPointError, OverflowError и ZeroDivisionError.
try: k = 1 / 0 except ArithmeticError: k = 0 print(k)
Также возможна инструкция except без аргументов, которая перехватывает вообще всё (и прерывание с клавиатуры, и системный выход и т. д.). Поэтому в такой форме инструкция except практически не используется, а используется except Exception. Однако чаще всего перехватывают исключения по одному, для упрощения отладки (вдруг вы ещё другую ошибку сделаете, а except её перехватит).
Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что-то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.
f = open('1.txt') ints = [] try: for line in f: ints.append(int(line)) except ValueError: print('Это не число. Выходим.') except Exception: print('Это что ещё такое?') else: print('Всё хорошо.') finally: f.close() print('Я закрыл файл.') # Именно в таком порядке: try, группа except, затем else, и только потом finally.
Чтобы в своей программе вызвать исключение надо воспользоваться командой raise.
Чтобы создать свое собственное исключение, надо унаследоваться от одного из уже существующих классов исключения:
class MyException(Exception): #создали свой класс. Ничего переопределять не обязательно pass raise MyException("My hovercraft is full of eels") #поднятие исключения
Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY.