io.FileIO - это сырое файловое I/O над файловым дескриптором ОС. Практически то же, что open(..., buffering=0) в бинарном режиме. Это RawIOBase-наследник, поэтому все паттерны RawIOBase тут применимы, но для файлов есть свои интересные сценарии.
Ниже, основные паттерны использования io.FileIO() в Python.
Типичный паттерн - явно сказать "хочу raw-уровень":
from io import FileIO ## то же самое, что open("data.bin", "rb", buffering=0) raw = FileIO("data.bin", "rb") buf = bytearray(4096) while True: n = raw.readinto(buf) if not n: break chunk = memoryview(buf)[:n] # обрабатываем chunk без лишних копий
Зачем:
read => системный read),FileIO (BufferedReader, шифратор, фреймер и т.п.).FileIO как "драйвер" под Buffered* и TextIOWrapperОчень общий паттерн:
import io raw = io.FileIO("log.txt", "ab") # FileIO (RawIOBase) buf = io.BufferedWriter(raw) # BufferedIOBase text = io.TextIOWrapper(buf, encoding="utf-8") text.write("hello\n") text.flush()
Чем это отличается от просто open("log.txt", "a", encoding="utf-8")?
вы контролируете слои:
BufferedWriter,raw (логирование, шифрование),Крутой паттерн FileIO: оборачивание уже существующего fd (например, из os.open, os.dup, subprocess и т.п.).
import os from io import FileIO fd = os.open("data.bin", os.O_RDONLY) f = FileIO(fd, mode="rb", closefd=True) # FileIO управляет закрытием fd data = f.read() f.close() # закроет и FileIO, и fd
Или наоборот - выдёргиваем fd, чтобы использовать на уровне ОС:
from io import FileIO import os f = FileIO("data.bin", "rb") fd = f.fileno() os.lseek(fd, 0, os.SEEK_SET) ## потом можно продолжать работать через f
Паттерны:
os.open (эксклюзив, неблокирующий и т.д.)Иногда надо открыть файл с флагами, которых нет у open(), например O_EXCL, O_DIRECT и т.п.
import os from io import FileIO flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL fd = os.open("unique.lock", flags, 0o600) try: f = FileIO(fd, "wb", closefd=True) f.write(b"locked\n") f.flush() # держим файл открытым, пока нужен lock finally: # Закроем при выходе f.close()
Паттерн:
os.open(...) с нужным набором флагов;FileIO для удобства работы.Для mmap.mmap() нужен файловый дескриптор. Паттерн:
import mmap from io import FileIO f = FileIO("data.bin", "r+b") # FileIO даёт интерфейс и fd mm = mmap.mmap(f.fileno(), 0) # 0 => весь файл ## теперь mm - как bytearray поверх файла print(mm[:10]) mm[0:4] = b"TEST" mm.flush() mm.close() f.close()
Здесь FileIO - просто удобный способ:
RawIOBase для ваших буферизаторов/фильтровВы пишете свой BufferedIOBase/фильтр и хотите протестировать его "по-взрослому" на реальном файле, а не только на BytesIO. Тогда:
import io raw = io.FileIO("test.bin", "w+b") # читаемый и записываемый buf = io.BufferedRandom(raw) # и чтение, и запись buf.write(b"hello") buf.seek(0) print(buf.read()) # b'hello'
То есть FileIO здесь - эталонный низкий уровень, чтобы убедиться, что ваш код работает не только с in-memory объектами.
FileIO для zero-copy с readintoПоскольку FileIO - RawIOBase, у него есть полноценный readinto. Паттерн для больших файлов:
from io import FileIO with FileIO("big.bin", "rb") as f: buf = bytearray(1024 * 1024) # 1 MB while True: n = f.readinto(buf) if not n: break chunk = memoryview(buf)[:n] # обрабатываем chunk без создания новых bytes
Плюс:
FileIOЧаще всего вам НЕ нужен FileIO, если:
open("file.txt", "r", encoding="utf-8");fileno() или специальные флаги os.open.В типичном прикладном коде паттерн проще:
with open("file.txt", "r", encoding="utf-8") as f: for line in f: ...
А вот когда:
тогда io.FileIO - правильный кирпичик.