Подтвердить что ты не робот

Поиск с конца файла, бросающего неподдерживаемое исключение

У меня есть этот фрагмент кода, и я пытаюсь искать назад с конца файла с помощью python:

f=open('D:\SGStat.txt','a');
    f.seek(0,2)
    f.seek(-3,2)

Это вызывает следующее исключение во время работы:

f.seek(-3,2)
io.UnsupportedOperation: can't do nonzero end-relative seeks

Мне что-то здесь не хватает?

4b9b3361

Ответ 1

Из документации для Python 3.2 и выше:

В текстовых файлах (открытых без строки b в строке режима) разрешен только поиск относительно начала файла (исключение - поиск в самом конце файла с seek(0, 2)).

Поэтому вы можете изменить свою программу на следующую:

f = open('D:\SGStat.txt', 'ab')
f.seek(0, 2)
f.seek(-3, 2)

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

Ответ 2

Существующие ответы действительно отвечают на вопрос, но не дают решения.

Из readthedocs:

Если файл открывается в текстовом режиме (без b), допустимы только смещения, возвращаемые функцией tell(). Использование других смещений вызывает неопределенное поведение.

Это подтверждается документацией, в которой говорится:

В текстовых файлах (которые открываются без b в строке режима) разрешен только поиск относительно начала файла [ os.SEEK_SET ]...

Это означает, что если у вас есть этот код из старого Python:

f.seek(-1, 1)   # seek -1 from current position

это будет выглядеть так в Python 3:

f.seek(f.tell() - 1, os.SEEK_SET)   # os.SEEK_SET == 0

Решение

Объединяя эту информацию, мы можем достичь цели ОП:
f.seek(0, os.SEEK_END)              # seek to end of file; f.seek(0, 2) is legal
f.seek(f.tell() - 3, os.SEEK_SET)   # go backwards 3 bytes

Ответ 3

Чтобы использовать поиск с текущей позиции и конца, вам нужно открыть текстовый файл в двоичном режиме. Посмотрите этот пример, где я создал файл "nums.txt" и поместил в него "ABCDEFGHIJKLMNOPQRSTUVWXYZ". Я читаю буквы строки "PYTHON" из файла и отображаю то же самое. Посмотрите код, который я запускаю в окнах Python 3.6 в Anaconda 4.2

    >>> file=open('nums.txt','rb')
    >>> file.seek(15,0)
    15
    >>> file.read(1).decode('utf-8')
    'P'
    >>> file.seek(8,1)
    24
    >>> file.read(1).decode('utf-8')
    'Y'
    >>> file.seek(-7,2)
    19
    >>> file.read(1).decode('utf-8')
    'T'
    >>> file.seek(7,0)
    7
    >>> file.read(1).decode('utf-8')
    'H'
    >>> file.seek(6,1)
    14
    >>> file.read(1).decode('utf-8')
    'O'
    >>> file.seek(-2,1)
    13
    >>> file.read(1).decode('utf-8')
    'N'