Чтение и запись файлов
Для работы с файлом его нужно открыть функцией open(). Она
возвращает файловый объект, который нужно закрыть методом .close():
f = open("hello.txt", "w", encoding="utf-8")
f.write("Привет, файл!\n")
f.close()
Но вручную закрывать файлы не принято — если между open и
close случится ошибка, файл «зависнет» открытым. Поэтому всегда
используют контекстный менеджер with:
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("Привет, файл!\n")
# после выхода из блока файл закроется автоматически, даже при ошибке
Режимы доступа
| Режим | Назначение |
|---|---|
"r" | чтение (по умолчанию). Файл должен существовать. |
"w" | запись. Файл создаётся или перезаписывается. |
"a" | дополнение (append). Данные дописываются в конец. |
"x" | создание. Ошибка, если файл уже есть. |
"r+" | чтение и запись. |
"b" | бинарный режим ("rb", "wb"). |
Всегда указывайте encoding="utf-8" для
текстовых файлов. Иначе на разных ОС кодировка может отличаться и появятся
«кракозябры» с русским текстом.
Чтение файла
# Целиком в одну строку
with open("hello.txt", encoding="utf-8") as f:
content = f.read()
print(content)
# Построчно
with open("hello.txt", encoding="utf-8") as f:
for line in f:
print(line.rstrip()) # rstrip убирает \n в конце
# Все строки в список
with open("hello.txt", encoding="utf-8") as f:
lines = f.readlines()
Построчное чтение через for line in f — самое
памято-эффективное: файл не загружается целиком в память. Это важно для
больших файлов (логов на гигабайты).
Запись файла
lines = ["Первая строка", "Вторая строка", "Третья строка"]
with open("output.txt", "w", encoding="utf-8") as f:
for line in lines:
f.write(line + "\n")
# Или короче через writelines (но без добавления \n)
with open("output.txt", "w", encoding="utf-8") as f:
f.writelines(line + "\n" for line in lines)
Модуль json
JSON — самый популярный формат для хранения и обмена данными. Модуль
json входит в стандартную библиотеку:
import json
data = {
"name": "Анна",
"age": 28,
"hobbies": ["чтение", "программирование"],
}
# Сериализация в строку
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
# Запись в файл
with open("user.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# Чтение из файла
with open("user.json", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["name"]) # Анна
ensure_ascii=False позволяет писать кириллицу напрямую, без
\u0410.... indent=2 делает красивый отступ.
dumps / dump / loads / load — как запомнить
dumps— в string (строку).dump— в файл.loads— из строки.load— из файла.
Исключения
Исключение — это ошибка во время выполнения. Если её не
обработать, программа упадёт. Обрабатывают через try/except:
try:
number = int(input("Введите число: "))
print(10 / number)
except ValueError:
print("Это не число!")
except ZeroDivisionError:
print("Делить на ноль нельзя!")
Можно ловить несколько исключений в одном except как кортеж:
try:
...
except (ValueError, TypeError) as e:
print(f"Ошибка ввода: {e}")
else и finally
else— выполняется, если исключения не было.finally— выполняется всегда, было исключение или нет (закрытие ресурсов).
try:
f = open("data.txt", encoding="utf-8")
except FileNotFoundError:
print("Файл не найден")
else:
content = f.read()
f.close()
print("Прочитано символов:", len(content))
finally:
print("Этот блок выполнится в любом случае")
Распространённые исключения
| Исключение | Когда возникает |
|---|---|
ValueError | Неверное значение (int("abc")) |
TypeError | Неверный тип ("a" + 1) |
KeyError | Нет такого ключа в словаре |
IndexError | Индекс за пределами списка |
FileNotFoundError | Файл не найден |
ZeroDivisionError | Деление на ноль |
AttributeError | Нет такого атрибута/метода |
Возбуждение исключений: raise
Свои ошибки можно «поднимать» через raise:
def set_age(age):
if age < 0:
raise ValueError("Возраст не может быть отрицательным")
return age
try:
set_age(-5)
except ValueError as e:
print(e) # Возраст не может быть отрицательным
Свои исключения
Для своих классов ошибок наследуются от Exception (мы
подробнее разберём классы в следующей главе, а здесь — минимальный пример):
class EmptyCartError(Exception):
'''Ошибка: попытка оформить пустую корзину.'''
pass
def checkout(cart):
if not cart:
raise EmptyCartError("Корзина пуста")
# ... оформление
Свои исключения делают обработку более выразительной:
except EmptyCartError понятнее, чем общий except Exception.
Хорошие практики
- Ловите конкретные исключения, а не «всё» через
except Exception. Иначе спрячете настоящие баги. - Не глушите исключения пустым
except: pass— хотя бы логируйте. - Узкая область try — оборачивайте только ту строку, которая может упасть.
- Контекстный менеджер
withдля любых файлов и ресурсов.
Кейс из реального проекта: задачи в JSON
Типичный сценарий — приложение сохраняет состояние в файл и читает его при старте. Здесь же — обработка случая «файла ещё нет»:
import json
from pathlib import Path
TASKS_FILE = Path("tasks.json")
def load_tasks() -> list[str]:
'''Загружает список задач из файла. Если файла нет — возвращает пустой список.'''
try:
with TASKS_FILE.open(encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return []
except json.JSONDecodeError:
print("Файл повреждён, начнём с пустого списка")
return []
def save_tasks(tasks: list[str]) -> None:
'''Сохраняет список задач в файл.'''
with TASKS_FILE.open("w", encoding="utf-8") as f:
json.dump(tasks, f, ensure_ascii=False, indent=2)
# Использование
tasks = load_tasks()
tasks.append("Выучить Python")
save_tasks(tasks)
pathlib.Path — современный способ работы с путями (вместо
os.path). Удобен тем, что работает одинаково на Windows и Unix.
Типичные ошибки
1. Открытие без with
f = open("x.txt") # если дальше ошибка — файл не закроется
# правильно
with open("x.txt") as f:
...
2. Голый except
try:
do_something()
except: # глушит ВСЁ, включая KeyboardInterrupt
pass
try:
do_something()
except ValueError: # ловим конкретное
...
3. Забыли encoding
# На Windows по умолчанию может быть cp1251 — кириллица сломается
with open("data.txt", "w") as f: # плохо
...
with open("data.txt", "w", encoding="utf-8") as f: # хорошо
...
Практика
- Запишите в файл 5 строк и прочитайте их обратно.
- Сохраните словарь с данными пользователя в JSON, затем загрузите и выведите.
- Напишите функцию
safe_divide(a, b), которая возвращаетNoneпри делении на ноль. - Прочитайте файл построчно и посчитайте количество строк и символов.
- Создайте своё исключение
InvalidScoreErrorи возбудите его при значении вне диапазона 0-100.
Итог
Мы научились читать и писать файлы через with open(), работать
с JSON через модуль json, обрабатывать ошибки через
try/except/else/finally, возбуждать исключения через
raise и создавать свои классы исключений. Эти навыки пригодятся в
финальном проекте — там мы будем хранить задачи в JSON-файле. В следующей
главе — модули и основы ООП.
Комментарии 0
Пока нет комментариев. Станьте первым!