Обработка и разбор файлов CSV, логов и специфических форматов в Python

Раздел: Ввод-вывод и файловая система -> Файловый ввод-вывод

Основные подходы к разбору файлов в Python

Наиболее эффективный способ парсинга CSV: использование модуля csv

Модуль csv встроен в Python и корректно обрабатывает кавычки, экранирование, разные разделители. Для файлов с заголовками удобен класс DictReader.

import csv

with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['name'], row['age'])

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

Вывод (для примера data.csv: name,age\nAlice,30\nBob,25):

Alice 30
Bob 25

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

Если разделитель иной (например, точка с запятой), укажите параметр delimiter=';'. Для файлов без заголовков используйте csv.reader.

Типичные проблемы:

  • Неверная кодировка - укажите encoding (utf-8, cp1251).
  • Пустые строки в конце файла - reader их пропускает, но проверяйте.
  • Строки с разным количеством полей - DictReader выдаст ошибку. Решение: csv.reader и ручная проверка.

Как разобрать CSV вручную без модуля csv?

with open('data.csv', 'r') as f:
    for line in f:
        parts = line.strip().split(',')
        print(parts)

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

Проблема: разделитель внутри кавычек (например, "Smith, John") будет разбит некорректно. Модуль csv решает это автоматически.

Как разобрать файл лога Apache (Common Log Format)?

import re

pattern = r'^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) \S+" (\d+) (\d+)'
with open('access.log', 'r') as f:
    for line in f:
        match = re.match(pattern, line)
        if match:
            ip, date, method, url, status, size = match.groups()
            print(ip, url)

Python index files (индексация файлов в python)

Этот подход гибок для любых логов. Ошибки: несоответствие формату строки - проверяйте None.

Как обработать custom файл с нестандартным разделителем и комментариями?

# Пример файла data.custom:
# name|age|city
Alice|30|New York
Bob|25|Los Angeles

with open('data.custom', 'r') as f:
    for line in f:
        line = line.strip()
        if not line or line.startswith('#'):
            continue
        parts = line.split('|')
        print(parts)

Проблемы: экранирование разделителя внутри поля не предусмотрено. Для сложных custom форматов используйте регулярные выражения или напишите свой парсер на основе конечного автомата.

Общие проблемы при парсинге любых файлов:

  • Большие файлы: читайте построчно, не загружайте в память целиком.
  • Битые строки: добавьте try-except и логирование.
  • Разные кодировки: используйте chardet для автоматического определения.
- Python config files (конфигурационные файлы в python)
- Python copy file (копирование файла в python)
- Python log file (логирование в файл в python)

Построчный парсинг CSV с генератором и обработкой ошибок

Пример
import csv

def parse_csv(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            try:
                yield int(row['age']), row['name']
            except (ValueError, KeyError) as e:
                print(f'Ошибка в строке {reader.line_num}: {e}')

for age, name in parse_csv('data.csv'):
    print(f'{name}: {age}')
Alice: 30
Bob: 25

Разбор Combined Log Format (Apache) с извлечением User-Agent

Пример
import re

# Combined Log Format: IP rfc931 authuser [date] "method resource protocol" status size "referer" "user-agent"
pattern = r'^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) \S+" (\d+) (\d+) "([^"]*)" "([^"]*)"'

with open('access.log', 'r') as f:
    for line in f:
        m = re.match(pattern, line)
        if m:
            ip, date, method, url, status, size, referer, ua = m.groups()
            print(f'IP: {ip}, URL: {url}, UA: {ua[:50]}')
IP: 192.168.1.1, URL: /index.html, UA: Mozilla/5.0...

Парсинг файла с фиксированной шириной столбцов (Fixed Width)

Пример
# Пример: строки вида "ALICE   30 NEW YORK" (10 символов имя, 5 возраст, 20 город)
widths = [10, 5, 20]
fields = ['name', 'age', 'city']

with open('fixed.txt', 'r') as f:
    for line in f:
        start = 0
        row = {}
        for i, w in enumerate(widths):
            raw = line[start:start+w].strip()
            row[fields[i]] = raw
            start += w
        print(row)
{'name': 'ALICE', 'age': '30', 'city': 'NEW YORK'}

Проблемы: строки разной длины, лишние пробелы. Решение: обрезать line.rstrip('\n') и проверять длину.

Использование csv.Sniffer для автоматического определения диалекта

Пример
import csv

with open('unknown.csv', 'r') as f:
    sample = f.read(1024)
    dialect = csv.Sniffer().sniff(sample)
    f.seek(0)
    reader = csv.reader(f, dialect=dialect)
    for row in reader:
        print(row)

Sniffer анализирует разделитель, кавычки, символ конца строки. Работает не всегда корректно на маленьких выборках.

Парсинг многострочных полей в CSV (с переносом строки внутри кавычек)

Пример
# Модуль csv поддерживает многострочные поля по умолчанию
import csv

with open('multiline.csv', 'r') as f:
    reader = csv.reader(f)
    for row in reader:
        # row может содержать строку с \n
        print(row)

Пример multiline.csv:

"Alice","Hello
world",30
"Bob","Single line",25

Первая запись вернет ['Alice', 'Hello\nworld', '30']. Важно: файл должен быть открыт с newline='' (по умолчанию), иначе будет нарушено экранирование.

Парсинг файла (CSV, log, custom) в Python - comments

En
Python parse file (python)