Tell: примеры (PYTHON)
tell: intОсновные характеристики метода tell
Метод tell() является частью объектов файлов в Python и применяется для получения текущей позиции указателя чтения-записи в файле. Эта позиция измеряется в байтах от начала файла. Использование метода не изменяет состояние файлового объекта.
Возвращаемое значение - целое число, обозначающее количество байтов от начала файла до текущей позиции указателя. Для текстовых файлов, открытых в режимах, подразумевающих преобразование (например, с указанием кодировки), возвращаемое значение может не соответствовать количеству считанных символов из-за различий в размере символов в байтах.
Метод не принимает аргументов и работает только с файловыми объектами, открытыми для чтения или записи. Его вызов на закрытом файле вызывает исключение ValueError.
Простые примеры применения
Пример с текстовым файлом в кодировке UTF-8:
with open('test.txt', 'w', encoding='utf-8') as f:
f.write('Привет')
with open('test.txt', 'r', encoding='utf-8') as f:
print(f.tell()) # 0
f.read(2)
print(f.tell()) # 4 (так как кириллические символы занимают 2 байта каждый)0 4
Пример с бинарным файлом:
with open('test.bin', 'wb') as f:
f.write(b'\x01\x02\x03\x04')
print(f.tell()) # 4
with open('test.bin', 'rb') as f:
print(f.tell()) # 0
f.read(2)
print(f.tell()) # 24 0 2
Аналогичные методы в Python
Метод seek(offset, whence) изменяет позицию указателя в файле. Принимает два аргумента: смещение и точку отсчета. Часто используется вместе с tell() для запоминания и восстановления позиции.
Метод file.seekable() проверяет поддержку случайного доступа к файлу. Если возвращает False, методы tell() и seek() могут быть недоступны.
Для потоков ввода-вывода из модуля io (например, StringIO, BytesIO) также существуют методы tell() и seek() с аналогичной функциональностью.
Аналоги в других языках программирования
В PHP функция ftell() возвращает текущую позицию в файловом указателе. Отличие: работает только с ресурсами файлов.
$fp = fopen('test.txt', 'r');
fread($fp, 3);
echo ftell($fp); // 3
fclose($fp);3
В JavaScript (Node.js) метод filehandle.read() не предоставляет прямого аналога. Позицию можно получить через filehandle.read() с опцией position или использовать fs.statSync для размера.
В Java метод getFilePointer() класса RandomAccessFile возвращает текущее смещение в файле. Похож на Python, но работает только с этим классом.
RandomAccessFile file = new RandomAccessFile("test.txt", "r");
file.readByte();
long pos = file.getFilePointer(); // 1
file.close();1
В C# свойство Position у классов FileStream или StreamReader позволяет получить или установить позицию. Отличие: это свойство, а не метод.
using (FileStream fs = new FileStream("test.txt", FileMode.Open))
{
fs.ReadByte();
Console.WriteLine(fs.Position); // 1
}1
Распространенные ошибки
Вызов метода на закрытом файловом объекте вызывает исключение:
f = open('test.txt', 'r')
f.close()
print(f.tell())ValueError: I/O operation on closed file.
Некорректная интерпретация позиции для текстовых файлов с многобайтовыми символами:
with open('test.txt', 'w', encoding='utf-8') as f:
f.write('αβγ') # греческие буквы
with open('test.txt', 'r', encoding='utf-8') as f:
f.read(1)
print(f.tell()) # 2, а не 12
Попытка использования на не поддерживающих операциях объектах (например, сетевое соединение):
import socket
s = socket.socket()
# s.tell() # AttributeError: 'socket' object has no attribute 'tell'Изменения в последних версиях Python
Специфических изменений в поведении метода tell() в последних основных версиях Python (3.8-3.12) не зафиксировано. Однако, обновления, касающиеся модуля io и обработки текстовых файлов, могут косвенно влиять на возвращаемые значения в определенных кодировках.
В Python 3.7 улучшена производительность некоторых файловых операций, что могло затронуть и работу tell() для стандартных файловых объектов.
Расширенные сценарии использования
Запоминание позиции для последующего возврата:
with open('data.txt', 'r') as f:
start_pos = f.tell()
chunk1 = f.read(10)
saved_pos = f.tell()
chunk2 = f.read(20)
f.seek(saved_pos) # возврат к сохраненной позиции
chunk2_again = f.read(20)
print(chunk2 == chunk2_again) # TrueTrue
Использование с бинарными файлами и структурой данных:
import struct
with open('data.bin', 'wb') as f:
f.write(struct.pack('i', 42)) # запись целого числа
print(f.tell()) # 4 (размер int в байтах)
with open('data.bin', 'rb') as f:
while f.tell() < 4:
data = f.read(1)
print(f"Position: {f.tell()}, Data: {data}")4 Position: 1, Data: b'*' Position: 2, Data: b'\x00' Position: 3, Data: b'\x00' Position: 4, Data: b'\x00'
Обработка большого файла с периодическим сохранением позиции:
import time
with open('large.log', 'r') as f:
last_pos = 0
while True:
f.seek(last_pos)
new_lines = f.readlines(5) # чтение по частям
if not new_lines:
break
last_pos = f.tell()
print(f"Read {len(new_lines)} lines from position {last_pos}")
time.sleep(0.1)