Seek: примеры (PYTHON)

Позиционирование в файлах: применение метода seek в Python
Раздел: Файлы, Позиционирование
seek(offset, whence): int

Основы функции seek

seek()

- метод файловых объектов в Python, позволяющий изменять текущую позицию для чтения/записи в файле. Используется при необходимости произвольного доступа к содержимому файла без последовательного чтения всего файла.

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

Аргументы:

  • offset (целое число) - количество байтов для смещения. Может быть положительным (вперед) или отрицательным (назад).
  • whence (необязательный, целое число) - точка отсчета смещения:
    • 0 (по умолчанию, os.SEEK_SET) - отсчет от начала файла
    • 1 (os.SEEK_CUR) - отсчет от текущей позиции
    • 2 (os.SEEK_END) - отсчет от конца файла

Возвращаемое значение: новое абсолютное положение в файле (в байтах от начала).

Базовые примеры использования

Пример 1: Смещение от начала файла

with open('test.txt', 'r') as f:
    f.seek(10)  # Переход к 10-му байту от начала
    print(f.read(5))
# Выведет 5 символов, начиная с 10-го байта

Пример 2: Смещение от текущей позиции

with open('test.txt', 'rb') as f:
    f.read(5)  # Читаем первые 5 байт
    f.seek(3, 1)  # Смещаемся на 3 байта вперед от текущей позиции
    print(f.tell())  # Показывает текущую позицию
8

Пример 3: Смещение от конца файла

with open('test.txt', 'rb') as f:
    f.seek(-5, 2)  # 5 байтов от конца файла
    print(f.read().decode())
# Выведет последние 5 байтов файла

Похожие функции в Python

tell() - возвращает текущую позицию в файле. Часто используется вместе с seek для запоминания и восстановления позиции.

read() и readline() - автоматически изменяют позицию чтения, но без точного контроля смещения.

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

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

Аналоги в других языках программирования

PHP: fseek() работает аналогично, но возвращает 0 при успехе и -1 при ошибке.

$fp = fopen('test.txt', 'r');
fseek($fp, 10);
echo fread($fp, 5);

JavaScript (Node.js): В асинхронном API fs.createReadStream поддерживает опцию start, но нет прямой аналогии seek.

Java: RandomAccessFile.seek() похож на Python-реализацию.

RandomAccessFile file = new RandomAccessFile("test.txt", "r");
file.seek(10);
byte[] bytes = new byte[5];
file.read(bytes);

C#: FileStream.Seek() имеет аналогичные параметры.

using (FileStream fs = new FileStream("test.txt", FileMode.Open))
{
    fs.Seek(10, SeekOrigin.Begin);
    byte[] buffer = new byte[5];
    fs.Read(buffer, 0, 5);
}

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

Ошибка 1: Смещение за пределы файла (при whence=0)

with open('test.txt', 'r') as f:
    f.seek(1000)  # Файл меньше 1000 байт
    print(f.read())
# Не вызывает ошибку, но последующее чтение вернет пустую строку

Ошибка 2: Отрицательное смещение при отсчете от начала

with open('test.txt', 'r') as f:
    f.seek(-5, 0)  # ValueError
ValueError: negative seek position

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

with open('test_utf8.txt', 'r', encoding='utf-8') as f:
    f.seek(2)  # Может попасть в середину символа UTF-8
    print(f.read(1))  # UnicodeDecodeError

Изменения в последних версиях

В Python 3.1 добавлена возможность использования seek() с аргументом whence как константами модуля os: os.SEEK_SET, os.SEEK_CUR, os.SEEK_END.

В Python 3.3 улучшена работа seek() с файлами, открытыми в текстовом режиме, для файлов, использующих кодировки с переменной длиной символов.

Начиная с Python 3.7, seek() в текстовых файлах поддерживается только для смещений, возвращаемых tell(), или нулевых смещений.

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

Пример 1: Чтение файла с конца

Пример python
def read_last_lines(filename, n=10):
    with open(filename, 'rb') as f:
        f.seek(0, 2)  # Переход в конец файла
        end_pos = f.tell()
        lines = []
        pos = end_pos
        
        while len(lines) <= n and pos > 0:
            pos = max(0, pos - 100)
            f.seek(pos)
            chunk = f.read(end_pos - pos)
            lines = chunk.split(b'\n') + lines
            pos -= 100
        
        return b'\n'.join(lines[-n:]).decode()

Пример 2: Редактирование бинарного файла

Пример python
with open('data.bin', 'r+b') as f:
    # Замена 4 байтов, начиная с позиции 20
    f.seek(20)
    original = f.read(4)
    print(f"Было: {original}")
    
    f.seek(20)  # Возврат к той же позиции
    f.write(b'NEW ')  # Запись новых данных
    
    f.seek(20)
    modified = f.read(4)
    print(f"Стало: {modified}")
Было: b'OLD '
Стало: b'NEW '

Пример 3: Построчный доступ к большим файлам

Пример python
def get_line_position(filename, line_num):
    positions = [0]
    with open(filename, 'r') as f:
        while f.readline():
            positions.append(f.tell())
    
    if line_num < len(positions):
        return positions[line_num]
    return None

# Быстрый доступ к строке 1000
pos = get_line_position('large.log', 1000)
if pos is not None:
    with open('large.log', 'r') as f:
        f.seek(pos)
        line = f.readline()
        print(f"Строка 1000: {line[:50]}...")

питон seek function comments

En
Seek Change stream position