Ответ 1
Стандартная open()
функция уже по умолчанию возвращает буферный файл (если он доступен на вашей платформе). Для файловых объектов, которые обычно полностью буферизуются.
Обычно здесь означает, что Python оставляет это для реализации C stdlib; он использует вызов fopen()
(wfopen()
в Windows для поддержки имен файлов UTF-16), что означает, что выбрана буферизация по умолчанию для файла; на Linux я считаю, что это будет 8kb. Для операции чистого чтения, такой как разбор XML, этот тип буферизации - именно то, что вы хотите.
Разбор XML, выполняемый iterparse
, считывает файл в кусках 16384 байт (16kb).
Если вы хотите управлять буферизацией, используйте аргумент ключевого слова buffering
:
open('foo.xml', buffering=(2<<16) + 8) # buffer enough for 8 full parser reads
который переопределит размер буфера по умолчанию (который, как я полагаю, будет соответствовать размеру файла или его кратности). В соответствии с этой статьей увеличение буфера чтения должно помочь, и, используя размер как минимум в 4 раза, ожидаемый размер блока чтения плюс 8 байтов улучшит производительность чтения. В приведенном выше примере я установил его в 8 раз больше размера чтения ElementTree.
Вы можете попробовать и посмотреть, будет ли io.open('foo.xml', 'rb', buffering=2<<16)
работать лучше. Открытие в режиме rb
даст вам io.BufferedReader
экземпляр.
Вы не хотите использовать io.TextIOWrapper
; базовый парсер expat хочет сырые данные, поскольку он будет декодировать вашу кодировку XML файла. Это только добавит дополнительные накладные расходы; вы получаете этот тип, если вместо этого открываете его в r
(textmode).
Использование io.open()
может дать вам большую гибкость и более богатый API, но основной объект C файла открывается с помощью open()
вместо fopen()
, и вся буферизация обрабатывается реализацией Python io.BufferedIOBase
.
Ваша проблема будет обрабатывать этот зверь, а не файл читает, я думаю. В любом случае кеш диска будет в значительной степени застрелен при чтении файла 800 ГБ.