Если вы забудете закрыть за собой файл, его закроет Python после того, как будет удалена последняя ссылка на него. Это означает, что, если вы откроете файл и не закроете его явно, он будет закрыт автоматически по завершении функции. Но вы можете открыть файл внутри длинной функции или даже основного раздела программы. Файл должен быть закрыт, чтобы все оставшиеся операции записи были завершены.
У Python имеются менеджеры контекста для очистки объектов вроде открытых файлов. Вы можете использовать конструкцию with выражение as переменная:
>>>> with open('relativity', 'wt') as fout:
>…·····fout.write(poem)
>…
Вот и все. После того как блок кода, расположенный под менеджером контекста (в этом случае одна строка), завершится (или нормально, или путем генерации исключения), файл будет закрыт автоматически.
Меняем позицию с помощью функции seek()
По мере чтения и записи Python отслеживает ваше местоположение в файле. Функция tell() возвращает ваше текущее смещение от начала файла в байтах. Функция seek() позволяет вам перейти к другому смещению в файле. Это значит, что вам не обязательно читать каждый байт файла, чтобы добраться до последнего, — вы можете использовать функцию seek(), чтобы сместиться к последнему байту и считать его.
Для примера воспользуемся 256-байтным бинарным файлом 'bfile', который мы создали ранее:
>>>> fin = open('bfile', 'rb')
>>>> fin.tell()
>0
Используем функцию seek(), чтобы перейти к предпоследнему байту файла:
>>>> fin.seek(255)
>255
Считаем все данные от текущей позиции до конца файла:
>>>> bdata = fin.read()
>>>> len(bdata)
>1
>>>> bdata[0]
>255
Функция seek() также возвращает текущее смещение.
Вы также можете вызвать функцию seek(), передав ей второй аргумент: seek(offset, origin):
• если значение origin равно 0 (по умолчанию), сместиться на offset байт с начала файла;
• если значение origin равно 1, сместиться на offset байт с текущей позиции;
• если значение origin равно 2, сместиться на offset байт с конца файла.
Эти значения также определены в стандартном модуле os:
>>>> import os
>>>> os.SEEK_SET
>0
>>>> os.SEEK_CUR
>1
>>>> os.SEEK_END
>2
Благодаря этому мы можем считать последний байт разными способами:
>>>> fin = open('bfile', 'rb')
Один байт перед концом файла:
>>>> fin.seek(-1, 2)
>255
>>>> fin.tell()
>255
Считать данные до конца файла:
>>>> bdata = fin.read()
>>>> len(bdata)
>1
>>>> bdata[0]
>255
Вам не нужно вызывать функцию tell(), чтобы работала функция seek(). Я только хотел показать, что обе эти функции возвращают одинаковое смещение.
Рассмотрим случай, когда мы вызываем функцию seek(), чтобы сместиться с текущей позиции: