Чтобы работать с сохранёнными данными, каждому программисту на Python необходимо знать про обработку файлов. Начиная с самого раннего выпуска, запись и чтение файлов встроены в Python. Если сравнить с другими языками типа С или Java, это довольно просто и требует немного строк кода. Более того, для этого не нужно загружать никаких дополнительных модулей.
Оглавление
Основы работы с файлами в Python
Общие методы для работы с файлами: open()
, чтобы открыть файл, seek()
, чтобы установить текущую позицию файла на заданное смещение, и close()
, чтобы закрыть файловый объект, когда вы закончите его использовать. Метод open()
возвращает ссылку на файл, представляющий файловый объект, чтобы получить доступ к чтению, записи или добавлению.
Когда открывается файл для чтения, Python нужно точно знать, как следует открыть файл в системе. Доступны два способа — обычное чтение и чтение в двоичном режиме. Соответствующие флаги имеют вид r
и rb
и должны быть определены, когда файл открывается встроенным методом open()
. Первый режим включает в себя интерпретацию специальных символов вроде “CR” (возврат каретки) and “LF” (перенос строки), чтобы отобразить разрыв строки, тогда как двоичный режим позволяет вам считывать данные в сыром виде — где данные хранятся как есть безо всякой дальнейшей интерпретации.
Как только вы открыли файл, методopen()
вернёт вам файловый объект. Эти файловые объекты содержат методы наподобиеread()
, readline()
, write()
, tell()
и seek()
. Хотя сами они (или подобные объекты) имеют больше методов, чем указано здесь, эти встречаются наиболее часто. Не каждый файловый объект нуждаются в имплементации всех методов работы с файлами.
Примеры
В этой статье мы будем объяснять, как читать файлы с помощью Python, через примеры. Некоторые из них включают построчное чтение, кусками (определённое количество строк за раз) и чтение в один заход. Также мы вам покажем способ прочесть отдельную строку из файла без поиска по всему файлу.
Построчное чтение файла
Первый пример вдохновлён двумя языками программирования: C и C++. Он довольно простой: открываем файл с помощью метода open()
, читаем файл построчно, используя метод readline()
, и выводим строку сразу же после чтения. Здесь применяется цикл while
, который непрерывно читает из файла, пока метод readline()
продолжает возвращать данные. В случае конца файла (EOF) цикл while
останавливается, и файловый объект закрывается, освобождая ресурсы для других программ.
# определим имя файла, который читаем filename = "test.txt" # открываем файл для чтения filehandle = open(filename, 'r') while True: # читаем одну строку line = filehandle.readline() if not line: break print(line) # закрываем указатель на этот файл filehandle.close()
Листинг 1
Как вы могли заметить, в листинге 1 мы явно открыли и закрыли файл (строки 5 и 14 соответственно). Хотя интерпретатор Python закрывает открытые файлы автоматически в конце исполнения программы, явно закрывать файл через close()
есть хороший стиль программирования, и это не следует забывать.
В качестве улучшения в языке Python 2.3 был введён удобный протокол итераторов. Это позволяет вам упростить цикл readline
следующим образом:
# определим имя файла, который читаем filename = "test.txt" for line in open(filename, 'r'): print(line)
Листинг 2
Здесть применяется цикл for
в комбинации с итератором in
. Файл открывается в строке 4 листинга 2. Текущая строка определяется с помощью итератора in
, считывается из файла, и её содержимое подаётся на выход stdout
в строке 5. Python скрывает открытие и закрытие файла, когда закончится исполнение. Хотя такой способ неэффективен, он позволяет вам больше не иметь дело с файловым потоком.
К сожалению, код выше менее явный и полагается на сборщик мусора Python, чтобы закрыть файл. Введённая в Python 2.5 команда with
инкапсулирует весь процесс ещё больше и также открывает и закрывает файлы лишь однажды на протяжении блока кода. Листинг 3 показывает, как использовать команду with
.
# определим имя файла, который читаем filename = "test.txt" with open(filename, 'r') as filehandle: for line in filehandle: print(line)
Листинг 3
Комбинация оператора with
и команды open()
открывает файл только один раз (строка 4). Если цикл for
завершён успешно, содержимое файла напечатано в поток stdout
(строки 5 и 6).
Более того, использование выражения with
даёт побочный эффект. Внутри интерпретатора Python создаётся блок try
–finally
, чтобы инкапсулировать чтение из файла. Листинг 4 показывает, что неизбежно случается внутри в Python с помощью блоков кодаwith
:
try: filehandle = open(filename, 'r') # что-то делаем finally: filehandle.close()
Листинг 4
Чтение файла как набора строк
До сих пор мы обрабатывали файл построчно. Это довольно медленный способ для огромных файлов, но его можно улучшить, если читать несколько строк одновременно. Чтобы этого добиться, в дело вступает метод islice()
из модуля itertools. Также он работает как итератор и возвращает набор данных, состоящий из n
строк. В конце файла результат может быть короче, и завершающий вызов вернёт пустой список.
from itertools import islice # определим имя файла, который читаем filename = "test.txt" # определим, сколько строк нужно прочесть number_of_lines = 5 with open(filename, 'r') as input_file: lines_cache = islice(input_file, number_of_lines) for current_line in lines_cache: print (current_line)
Листинг 5
Чтение определённой строки из файла
Используя показанные выше методы, мы можем также выполнить другие полезные действия, например, прочесть определённую строку из файла. Чтобы это сделать, применим счётчик и напечатаем соответствующую строку, когда дойдём до неё, проходя итерациями по файлу.
# определим имя файла, который читаем filename = "test.txt" # определим номер строки line_number = 3 print ("line %i of %s is: " % (line_number, filename)) with open(filename, 'r') as filehandle: current_line = 1 for line in filehandle: if current_line == line_number: print(line) break current_line += 1
Листинг 6
Листинг 6 достаточно просто понять, но он немного больше, чем предыдущие примеры. Его можно сократить, используя модуль linecache. Листинг 7 поазывает, как упростить код с помощью метода getline()
. Если запрашиваемая строка выпадает из ряда валидных строк в файле, то метод getline()
взамен возвращает пустую строку.
# импортируем модуль linecache import linecache # определим имя файла, который читаем filename = "test.txt" # определим номер строки line_number = 3 # получим определённую строку line = linecache.getline(filename, line_number) print ("line %i of %s:" % (line_number, filename)) print (line)
Листинг 7
Чтение из всего файла целиком
В заключение мы посмотрим на совершенно другой случай по сравнению с предыдущим примером — прочитаем файл за один раз. Имейте в виду, что во многих случаях вам нужно достаточно места на компьютере, чтобы прочесть файл в память целиком. Листинг 8 использует комбинацию выражения with
и метода read()
. В этом случае мы применим read()
, чтобы загрузить содержимое файла как поток данных.
# определим имя файла, который читаем filename = "test.txt" with open(filename, 'r') as filehandle: filecontent = filehandle.read() print (filecontent)
Листинг 8
Python также предлагает метод readlines()
, похожий на метод readline()
из первого примера. В отличие от read()
, содержимое файла сохраняется в список, где каждый элемент есть строка содержимого. Листинг 9 показывает, как получить доступ к этим данным:
# определим имя файла, который читаем filename = "test.txt" with open(filename, 'r') as filehandle: filecontent = filehandle.readlines() for line in filecontent: print (line)
Листинг 9
Хотя readlines()
будет читать содержимое из файла, пока не наткнётся на EOF (конец файла), не забывайте, что вы также можете ограничить количество прочитанного параметром sizehint
, — числом байт, которое нужно прочесть.
Вывод
Как обычно, есть больше одного способа прочитать содержимое файла. В плане скорости все они примерно одинаковы. Какое решение для вас работает лучше, зависит от решаемых вами задач. Мы думаем, что было бы полезно увидеть разные возможности и выбрать более подходящее решение.
Хотя Python значительно упрощает процесс чтения файлов, иногда он бывает довольно сложным, в таком случае рекомендую взглянуть на официальную документацию Python для дальнейшего ознакомления.