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

Раздел: Продвинутый Python -> Файловый ввод-вывод

Задания на работу с файлами в Python: продвинутые примеры

Рассмотрим типовое задание: чтение файла логов access.log, отбор строк с кодами ошибок 5xx и запись в errors.log. Ниже представлены различные подходы с оценкой эффективности и типичных проблем.

Наиболее эффективное решение: контекстный менеджер + построчное чтение

with open('access.log', 'r', encoding='utf-8') as infile, \
     open('errors.log', 'w', encoding='utf-8') as outfile:
    for line in infile:
        if ' 5' in line:
            outfile.write(line)

ввод программ на python (ввод данных в программе python)

Пояснение: менеджер контекста гарантирует закрытие файлов даже при возникновении ошибок. Построчное чтение не загружает весь файл в память, что оптимально для больших логов. Проверка ' 5' in line работает для типового формата, когда код ошибки находится после пробела (например, строка содержит ' 500 ').

Типичные ошибки и способы их решения

  • Забыли указать параметр encoding - может вызвать UnicodeDecodeError для файлов с не-ASCII символами. Решение: всегда указывать явно кодировку.
  • Проверка ' 5' может захватить ложные совпадения, например, ' 50000' или ' 5000'. Решение: использовать регулярное выражение для точного поиска кода ошибки (например, pattern = r'\s5\d{2}\s').
  • Строки могут содержать символы перевода строки с разными окончаниями (\r\n, \n). При записи line уже содержит перевод, поэтому дополнительный \n не требуется.
  • Ошибка FileNotFoundError, если файл не существует. Решение: обернуть код в try-except или проверять существование через Path.exists().

Вариант 1: Чтение всего файла в память

Как прочитать файл целиком и обработать все строки в памяти?

with open('access.log', 'r', encoding='utf-8') as f:
    lines = f.readlines()
with open('errors.log', 'w', encoding='utf-8') as f:
    for line in lines:
        if ' 5' in line:
            f.write(line)

Python file io (ввод-вывод файлов в python)

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

Типичные ошибки: при работе с большими файлами - переполнение памяти. Решение: заменить на построчное чтение из варианта rbase.

Вариант 2: Функциональный стиль с filter()

Как использовать встроенную функцию filter() для фильтрации строк?

def is_error(line):
    return ' 5' in line

with open('access.log', 'r', encoding='utf-8') as infile, \
     open('errors.log', 'w', encoding='utf-8') as outfile:
    outfile.writelines(filter(is_error, infile))

Python temp files (временные файлы в python)

Функция filter() возвращает итератор, поэтому файл читается лениво. Код получается лаконичным, но может быть сложнее для отладки. Такой подход хорошо сочетается с другими функциями высшего порядка.

Проблемы: filter() не принимает дополнительные аргументы для функции, поэтому приходится определять отдельную функцию. Ошибка: если файл не открывается корректно - то же, что и в rbase.

Вариант 3: Использование pathlib

Как применить современный модуль pathlib для чтения и записи?

from pathlib import Path

in_path = Path('access.log')
out_path = Path('errors.log')

text = in_path.read_text(encoding='utf-8')
lines = text.splitlines(keepends=True)
errors = [line for line in lines if ' 5' in line]
out_path.write_text(''.join(errors), encoding='utf-8')

Методы read_text() и write_text() крайне удобны для небольших файлов. Недостаток - полная загрузка файла в память и создание промежуточных списков. Для большого файла лучше использовать построчные методы.

Ошибка: splitlines() по умолчанию удаляет символы перевода строки. Используйте keepends=True, чтобы сохранить их. Иначе строки сольются при записи.

- Python file utf 8 (кодировка utf-8 для файлов в python)
- Python config files (конфигурационные файлы в python)
- Python copy file (копирование файла в python)

Расширенные примеры работы с файлами в Python

Пример 1: Использование mmap для быстрого поиска в большом файле

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

Пример
import mmap

with open('access.log', 'r+b') as f:
    mm = mmap.mmap(f.fileno(), 0)
    offset = 0
    errors = []
    while True:
        pos = mm.find(b' 5', offset)
        if pos == -1:
            break
        end = mm.find(b'\n', pos)
        if end == -1:
            end = len(mm)
        line = mm[pos:end].decode('utf-8')
        errors.append(line)
        offset = end + 1
    mm.close()

with open('errors_mmap.log', 'w', encoding='utf-8') as f:
    f.writelines(errors)
Результат: файл errors_mmap.log содержит строки логов с кодами 5xx. Время выполнения для файла размером 2 ГБ сокращается по сравнению с построчным чтением благодаря прямому доступу к памяти.

Важно: mmap.mmap() требует режим открытия файла 'r+b' (чтение+запись в бинарном режиме). Для чистого чтения можно использовать os.open().

Пример 2: Работа с CSV и DictWriter

Когда данные структурированы (например, таблица логов), удобно применять модуль csv.

Пример
import csv

with open('data.csv', 'r', newline='', encoding='utf-8') as infile:
    reader = csv.DictReader(infile)
    rows = [row for row in reader if int(row['status']) >= 500]

with open('errors.csv', 'w', newline='', encoding='utf-8') as outfile:
    fieldnames = reader.fieldnames
    writer = csv.DictWriter(outfile, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(rows)
Результат: файл errors.csv содержит только строки со статусом >=500, сохранённые в том же CSV-формате с заголовками.

Пример 3: Временный файл с помощью tempfile

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

Пример
import tempfile
import os

with tempfile.NamedTemporaryFile(mode='w+', suffix='.log', delete=True) as tmp:
    tmp.write('temp data\n')
    tmp.flush()
    # Используем путь к временному файлу
    print('Temp file path:', tmp.name)
    # Файл будет удалён при выходе из контекста
Вывод: Temp file path: /tmp/tmpabc123.log
После завершения блока файл удаляется.

Пример 4: Копирование бинарного файла с shutil.copyfileobj

Для копирования больших бинарных данных (изображения, архивы) эффективно использовать буферизированное копирование.

Пример
import shutil

with open('image.jpg', 'rb') as src, open('copy.jpg', 'wb') as dst:
    shutil.copyfileobj(src, dst, length=1024*1024)  # 1 МБ буфер
Результат: создаётся точная копия файла image.jpg под именем copy.jpg.

Пример 5: Эмуляция файла с помощью io.StringIO

Для модульного тестирования или работы со строками как с файлами применяется StringIO из модуля io.

Пример
from io import StringIO

buffer = StringIO()
buffer.write('line1\nline2\n')
buffer.seek(0)
for line in buffer:
    print(line.strip())
Вывод:
line1
line2

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

Задания на работу с файлами в Python - comments

En
задания файлы python (python)