Изменение содержимого файлов в Python: практические приёмы

Раздел: Ввод-вывод -> Файловый ввод-вывод

Изменение файла в Python: обзор подходов

Python предоставляет несколько способов модификации файлов. Выбор метода зависит от объёма данных, структуры файла и требуемой производительности. Ниже рассмотрены основные варианты с примерами кода и указанием возможных проблем.

Как перезаписать файл новым содержимым или дополнить его в конце?

Самый распространённый способ - открыть файл в режиме 'w' (запись с очисткой) или 'a' (добавление в конец). Это эффективно, когда нужно полностью заменить содержимое или добавить новые данные без чтения старого.

Пример: записать список строк в файл.


lines = ['Первая строка', 'Вторая строка', 'Третья строка']
with open('example.txt', 'w', encoding='utf-8') as f:
    f.write('\n'.join(lines))
    

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

Файл example.txt будет создан (или перезаписан) с тремя строками.
    

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

Пример: добавить текст в конец файла.


with open('example.txt', 'a', encoding='utf-8') as f:
    f.write('\nДополнительная строка')
    

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

Возможные проблемы:

  • Режим 'w' уничтожает все предыдущее содержимое. Если нужно изменить только часть файла, этот способ не подходит.
  • При записи без явного указания кодировки могут возникнуть ошибки для не-ASCII символов. Всегда указывайте encoding='utf-8' или другую подходящую кодировку.
  • Ошибка FileNotFoundError в режиме 'a' не возникает - файл будет создан автоматически.

Как изменить содержимое файла, загрузив его целиком в память?

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


with open('data.txt', 'r', encoding='utf-8') as f:
    text = f.read()

# Замена всех вхождений 'старое' на 'новое'
text = text.replace('старое', 'новое')

with open('data.txt', 'w', encoding='utf-8') as f:
    f.write(text)
    

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

Типичные ошибки:

  • Для очень больших файлов может не хватить оперативной памяти.
  • При работе с бинарными файлами нужно открывать в режиме 'rb'/'wb'.
  • Замена через str.replace() может быть неэффективной для частых операций.

Как изменить большой файл построчно без загрузки в память?

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


import os
import tempfile

input_file = 'large_log.txt'
tmp_fd, tmp_path = tempfile.mkstemp()

with open(input_file, 'r', encoding='utf-8') as fin, \
     open(tmp_path, 'w', encoding='utf-8') as fout:
    for line in fin:
        modified_line = line.replace('ERROR', 'WARNING')
        fout.write(modified_line)

os.close(tmp_fd)
os.replace(tmp_path, input_file)
    

File python class (класс для работы с файлами в python)

Возможные сложности:

  • Необходимо гарантировать атомарность замены. Метод os.replace() обеспечивает атомарность на большинстве файловых систем.
  • При работе с огромными строками (без символа новой строки) может потребоваться чтение фиксированными блоками.

Как вставить данные в середину существующего файла?

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


with open('data.txt', 'r+', encoding='utf-8') as f:
    content = f.read()
    position = content.find('\nВставка')
    if position != -1:
        new_content = content[:position] + '\nНовая строка' + content[position:]
        f.seek(0)
        f.write(new_content)
        f.truncate()
    

Python file utf 8 (кодировка utf-8 для файлов в python)

Проблемы:

  • Для больших файлов операция будет медленной из-за копирования данных.
  • Необходимо синхронизировать позицию и размер файла через truncate().

Как изменить конкретные байты в бинарном файле?

Используется режим 'rb+' и метод seek() для позиционирования.


with open('image.bin', 'rb+') as f:
    f.seek(100)  # перейти к 101-му байту
    f.write(b'\x00\x00')  # записать два нулевых байта
    

Python config files (конфигурационные файлы в python)

Ошибки:

  • Запись в середине бинарного файла без учета структуры может сделать файл нечитаемым.
  • Некорректное использование seek (например, начало отсчёта с конца) требует отрицательного смещения.

Как изменить файл на месте с помощью модуля fileinput?

Модуль fileinput позволяет итерироваться по строкам файла и перенаправлять вывод обратно в тот же файл через параметр inplace=True.


import fileinput

with fileinput.FileInput('data.txt', inplace=True, backup='.bak') as f:
    for line in f:
        print(line.replace('old', 'new'), end='')
    

Python copy file (копирование файла в python)

Замечания:

  • Создаётся резервная копия (параметр backup).
  • Функция print() по умолчанию добавляет новую строку, поэтому end='' обязателен.

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

Библиотека pathlib предоставляет удобные методы для работы с путями. Полная перезапись файла новым содержимым:


from pathlib import Path

path = Path('example.txt')
path.write_text('Новое содержимое', encoding='utf-8')
    

Python log file (логирование в файл в python)

Для добавления в конец:


with path.open('a', encoding='utf-8') as f:
    f.write('Дополнение')
    

Ограничения:

  • Метод write_text() подходит только для текстовых файлов. Для бинарных используйте write_bytes().
  • При большой записи может быть неэффективно из-за полной загрузки в память.
- File handle python (обработка файлов в python)
- Python open file read (открытие файла для чтения в python)
- Python file position (позиционирование в файле python)

Расширенные примеры изменения файлов

1. Замена строки в большом лог-файле с помощью временного файла

Пусть имеется лог-файл размером 500 МБ. Необходимо заменить все уровни 'ERROR' на 'WARNING', не загружая файл в память целиком.

Пример

import os
import tempfile
import shutil

log_file = 'server.log'
temp_file = tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', delete=False)

try:
    with open(log_file, 'r', encoding='utf-8') as fin, temp_file as fout:
        for line in fin:
            fout.write(line.replace('ERROR', 'WARNING'))
    temp_file.close()
    shutil.move(temp_file.name, log_file)
except Exception as e:
    os.unlink(temp_file.name)
    raise
После выполнения исходный файл server.log будет заменён, а оригинальные 'ERROR' станут 'WARNING'.

Пояснение: Временный файл создаётся в той же файловой системе для ускорения операции. Если во время обработки возникает исключение, временный файл удаляется, чтобы не оставлять мусор.

2. Изменение параметров в конфигурационном файле INI

Допустим, нужно увеличить параметр 'timeout' в файле config.ini.

Пример

import configparser

config = configparser.ConfigParser()
config.read('config.ini')

if 'DEFAULT' in config and 'timeout' in config['DEFAULT']:
    current = int(config['DEFAULT']['timeout'])
    config['DEFAULT']['timeout'] = str(current + 10)
    with open('config.ini', 'w', encoding='utf-8') as f:
        config.write(f)
Значение timeout увеличится на 10. Файл будет перезаписан с сохранением комментариев (если они были).

3. Эффективное изменение с помощью mmap (отображение в память)

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

Пример

import mmap
import os

filename = 'data.bin'
with open(filename, 'r+b') as f:
    with mmap.mmap(f.fileno(), 0) as mm:
        # Ищем сигнатуру 0x1A2B3C4D
        offset = mm.find(b'\x1A\x2B\x3C\x4D')
        if offset != -1:
            # Заменяем на 0x0A0B0C0D
            mm[offset:offset+4] = b'\x0A\x0B\x0C\x0D' 
В файле data.bin будет изменена 4-байтовая последовательность без копирования всего файла в память Python.

4. Пакетное изменение нескольких файлов с регулярными выражениями

Необходимо во всех HTML-файлах в каталоге заменить 'http://' на 'https://' и создать резервную копию.

Пример

import re
import os
from glob import glob

for filepath in glob('*.html'):
    backup_path = filepath + '.bak'
    os.rename(filepath, backup_path)
    
    with open(backup_path, 'r', encoding='utf-8') as fin:
        content = fin.read()
    
    new_content = re.sub(r'http://', 'https://', content)
    
    with open(filepath, 'w', encoding='utf-8') as fout:
        fout.write(new_content)
Все *.html файлы будут содержать 'https://' вместо 'http://', а оригиналы сохранены с расширением .bak.

Изменение файла в Python - comments

En
Python change file (python)