W3docs

Чтение файлов в Python – Полное руководство

Все способы чтения файлов в Python: read(), readline(), readlines(), итерация по строкам, бинарный режим, кодировки, pathlib и работа с большими файлами.

Чтение файлов — одна из самых распространённых задач в Python: загрузка конфигурации, обработка логов, импорт данных CSV или чтение бинарных ресурсов. В этой главе рассматриваются все методы Python для чтения содержимого файлов: от простейшего вызова read() до эффективной итерации по строкам, бинарного режима, работы с кодировками, управления позицией в файле и современного API pathlib.

Открытие файла для чтения

Любая операция с файлом начинается со встроенной функции open(). Чтобы открыть файл в режиме чтения, укажите строку режима "r" (она используется по умолчанию, если режим не задан):

file_object = open("notes.txt", "r", encoding="utf-8")
  • "r" — открыть для чтения; вызывает FileNotFoundError, если файл не существует.
  • encoding="utf-8" — всегда указывайте кодировку для текстовых файлов, чтобы код одинаково работал на Windows, macOS и Linux.

Всегда используйте блок with

Самый безопасный способ открыть файл — внутри оператора with. Python автоматически закроет файл при выходе из блока — даже если возникнет исключение — что предотвращает утечку ресурсов и гарантирует сброс буферизованных данных.

with open("notes.txt", "r", encoding="utf-8") as f:
    contents = f.read()
# File is automatically closed here

Вызов open() вне блока with и забытый file.close() — частая причина ошибки «too many open files» в долгоработающих скриптах.

Чтение всего файла с помощью read()

read() возвращает полное содержимое файла в виде одной строки.

Прочитать весь файл сразу

with open("notes.txt", "r", encoding="utf-8") as f:
    contents = f.read()

print(contents)

Используйте read(), когда:

  • Файл достаточно мал, чтобы поместиться в памяти.
  • Нужен полный текст в виде одной строки (например, для разбора или поиска).

Для потенциально больших файлов (логи, дампы данных) предпочтительнее подходы с построчным чтением, описанные ниже.

Чтение фиксированного количества символов

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

Прочитать первые 50 символов

with open("notes.txt", "r", encoding="utf-8") as f:
    first_chunk = f.read(50)
    second_chunk = f.read(50)

print(repr(first_chunk))
print(repr(second_chunk))

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

Построчное чтение с помощью readline()

readline() читает одну строку из файла, включая завершающий символ новой строки \n. При достижении конца файла возвращается пустая строка "", что упрощает цикл до EOF.

Читать файл построчно с помощью readline()

with open("notes.txt", "r", encoding="utf-8") as f:
    line = f.readline()
    while line:
        print(line, end="")   # line already contains '\n'
        line = f.readline()

Аргумент end="" в print() предотвращает появление двойного переноса строки (одного из файла и одного от стандартного поведения print).

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

Итерация по строкам (наиболее идиоматичный способ)

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

Итерация по строкам с помощью цикла for

with open("notes.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line, end="")

Этот шаблон предпочтительнее read() + split("\n") и вызова readline() в цикле while, поскольку он короче и корректно обрабатывает все граничные случаи (в том числе файлы без завершающего символа новой строки).

Поиск по шаблону во время итерации

with open("server.log", "r", encoding="utf-8") as f:
    for line in f:
        if "ERROR" in line:
            print(line, end="")

Чтение всех строк в список с помощью readlines()

readlines() возвращает список, где каждый элемент — одна строка файла (с включённым символом новой строки). При этом весь файл загружается в память.

Прочитать все строки в список

with open("notes.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()

print(lines[0])        # first line
print(lines[-1])       # last line
print(len(lines))      # total number of lines

Используйте readlines(), когда нужен произвольный доступ к конкретным строкам по индексу. Для последовательной обработки сверху вниз шаблон for line in f более экономен по памяти.

Удаление символов новой строки

Строки, возвращаемые readline(), readlines() и итерацией в цикле for, содержат завершающий \n. Используйте .strip() или .rstrip("\n") для его удаления:

with open("notes.txt", "r", encoding="utf-8") as f:
    lines = [line.rstrip("\n") for line in f]

print(lines)  # ['Line one', 'Line two', 'Line three']

Выбор подходящего метода чтения

МетодВозвращаетЗагружает весь файл?Лучше всего подходит для
f.read()strДаМаленькие файлы, разбор полного текста
f.read(n)strНет (блоками)Потоковая передача фиксированного размера
f.readline()strНетУсловная построчная остановка
for line in fstr (по одной за итерацию)НетПоследовательная построчная обработка
f.readlines()list[str]ДаПроизвольный доступ к строкам по индексу

Позиция в файле: tell() и seek()

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

  • tell() — возвращает текущее смещение в байтах от начала файла.
  • seek(offset, whence=0) — перемещает указатель. При whence=0 (по умолчанию) смещение отсчитывается от начала; whence=1 — от текущей позиции; whence=2 — от конца.

Прочитать файл дважды с помощью seek(0)

with open("notes.txt", "r", encoding="utf-8") as f:
    first_pass = f.read()
    print(f"Position after first read: {f.tell()}")

    f.seek(0)   # rewind to the beginning
    second_pass = f.read()

print(first_pass == second_pass)  # True

seek() особенно полезен в режиме "r+" (чтение и запись), когда нужно прочитать часть файла, а затем перезаписать определённый фрагмент в том же вызове open().

Обработка ошибок при чтении

Хорошо написанный скрипт всегда предусматривает возможные сбои при чтении файла.

Обработать распространённые ошибки чтения

try:
    with open("data.txt", "r", encoding="utf-8") as f:
        content = f.read()
except FileNotFoundError:
    print("Error: the file does not exist.")
except PermissionError:
    print("Error: you do not have permission to read this file.")
except UnicodeDecodeError:
    print("Error: the file contains bytes that are not valid UTF-8.")
except OSError as e:
    print(f"OS error: {e}")

Распространённые исключения, с которыми вы столкнётесь:

ИсключениеКогда возникает
FileNotFoundErrorПуть не указывает на существующий файл
PermissionErrorУ процесса нет прав на чтение
IsADirectoryErrorПуть указывает на директорию, а не на файл
UnicodeDecodeErrorБайты файла не соответствуют указанной кодировке

Подробное руководство по обработке исключений см. в Python Try Except.

Кодировка символов

Когда Python открывает файл в текстовом режиме, он должен знать, как преобразовать байты в символы. Всегда явно передавайте encoding=, не полагаясь на платформенное значение по умолчанию, которое различается на Windows (cp1252) и большинстве Unix-систем (utf-8).

Распространённые значения кодировок:

КодировкаПрименять когда
"utf-8"Современные файлы, веб-контент, большинство Python-проектов
"utf-8-sig"UTF-8-файлы, созданные инструментами Windows с BOM в начале
"latin-1"Устаревшие западноевропейские файлы
"cp1252"Текстовые файлы Windows ANSI

Обнаружение или игнорирование проблем с кодировкой:

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

with open("mystery.txt", "r", encoding="utf-8", errors="replace") as f:
    content = f.read()

Другие значения параметра errors: "ignore" (молча пропускать плохие байты) и "strict" (по умолчанию — вызывает UnicodeDecodeError).

Чтение бинарных файлов

Откройте файл в бинарном режиме, добавив "b" к строке режима ("rb"). Бинарный режим возвращает объекты bytes вместо строк, что подходит для изображений, аудио, сжатых архивов, исполняемых файлов и любых нетекстовых данных.

Прочитать бинарный файл

with open("photo.jpg", "rb") as f:
    data = f.read()

print(type(data))   # <class 'bytes'>
print(len(data))    # size in bytes

Скопировать бинарный файл

with open("photo.jpg", "rb") as src:
    data = src.read()

with open("photo_backup.jpg", "wb") as dst:
    dst.write(data)

Не указывайте encoding в бинарном режиме — Python вызовет ValueError, если попытаться.

Эффективное чтение больших файлов

Загрузка многогигабайтного файла с помощью read() может исчерпать системную память. Решения:

Построчная итерация (текстовые файлы)

with open("huge_log.txt", "r", encoding="utf-8") as f:
    for line in f:
        process(line)   # only one line in memory at a time

Блоки фиксированного размера (бинарные файлы)

CHUNK_SIZE = 65536  # 64 KB

with open("large_file.bin", "rb") as f:
    while True:
        chunk = f.read(CHUNK_SIZE)
        if not chunk:
            break
        process(chunk)

Оба шаблона сохраняют постоянный объём используемой памяти независимо от размера файла.

Чтение файлов с помощью pathlib

В Python 3.4 был введён pathlib.Path, предоставляющий объектно-ориентированный интерфейс к путям файловой системы. Для простого однократного чтения и записи объекты Path лаконичнее, чем open().

Читать текст с помощью Path.read_text()

from pathlib import Path

content = Path("notes.txt").read_text(encoding="utf-8")
print(content)

Читать байты с помощью Path.read_bytes()

from pathlib import Path

data = Path("photo.jpg").read_bytes()
print(len(data))  # file size in bytes

read_text() и read_bytes() открывают файл, читают всё его содержимое и закрывают его в одном вызове. Используйте их для маленьких файлов, когда нужно просто получить содержимое. Используйте open() с блоком with, когда требуется построчная итерация, блочное чтение, seek() или любой другой тонкий контроль.

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

from pathlib import Path

p = Path("data.txt")
if p.exists() and p.is_file():
    content = p.read_text(encoding="utf-8")
else:
    print("File not found.")

Примечание: p.exists() может вернуть устаревший результат в многопоточном коде. В таких случаях безопаснее попытаться выполнить чтение и перехватить FileNotFoundError.

Практический пример: чтение простого конфигурационного файла

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

Разбор конфигурационного файла в формате key=value

from pathlib import Path

def load_config(path):
    config = {}
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#"):
                continue          # skip blank lines and comments
            key, _, value = line.partition("=")
            config[key.strip()] = value.strip()
    return config

# Example config.txt contents:
# host = localhost
# port = 8080
# debug = true

config = load_config("config.txt")
# config == {'host': 'localhost', 'port': '8080', 'debug': 'true'}

str.partition("=") разбивает строку только по первому =, поэтому значения, содержащие = (например, строки Base64), обрабатываются корректно.

Связанные главы

  • Python File Handling — режимы открытия, оператор with, seek(), бинарные файлы, обзор pathlib
  • Python Write / Create Files — запись, создание и дополнение файлов
  • Python Delete Files — безопасное удаление файлов и директорий
  • Python Try Except — обработка исключений в Python
  • Python CSV — чтение и запись CSV-файлов с помощью модуля csv
Was this page helpful?