Нарезка файла в Python
Я недавно работал над скриптами, которые берут файл, куски его и анализируют каждую часть. Поскольку позиции chunking зависят от содержимого, мне нужно прочитать его по одному байт за раз. Я не нуждаюсь в произвольном доступе, просто читая его линейно от начала до конца, выбирая определенные позиции, когда я иду, и уступаю содержимое фрагмента из предыдущей выбранной позиции в текущую.
Было очень удобно использовать файл с отображением памяти, обернутый bytearray
. Вместо того, чтобы уступать кусок, я получаю смещение и размер куска, оставляя внешнюю функцию срезать его.
Это было также быстрее, чем накапливать текущий кусок в bytearray
(и намного быстрее, чем накапливать в bytes
!). Но у меня есть определенные опасения, которые я хотел бы затронуть:
- Является ли копирование данных bytearray?
- Я открываю файл как
rb
и mmap
с помощью access=mmap.ACCESS_READ
. Но bytearray
является, в принципе, изменчивым контейнером. Это проблема производительности? Есть ли контейнер для чтения, который я должен использовать?
- Поскольку я не накапливаю в буфере, я произвольно получаю доступ к
bytearray
(и, следовательно, к базовому файлу). Несмотря на то, что это может быть буферизировано, я боюсь, что будут проблемы в зависимости от размера файла и системной памяти. Это действительно проблема?
Ответы
Ответ 1
-
Преобразование одного объекта в изменяемый объект приводит к копированию данных. Вы можете напрямую прочитать файл в bytearray, используя:
f = open(FILENAME, 'rb')
data = bytearray(os.path.getsize(FILENAME))
f.readinto(data)
from http://eli.thegreenplace.net/2011/11/28/less-copies-in-python-with-the-buffer-protocol-and-memoryviews#id12
-
Существует строка для преобразования bytearray, поэтому есть потенциальная проблема с производительностью.
-
bytearray - это массив, поэтому он может достигать предела PY_SSIZE_T_MAX/sizeof (PyObject *). Для получения дополнительной информации вы можете посетить
Как большой может получить массив Python?
Ответ 2
Вы можете сделать этот маленький взлом.
import mmap
class memmap(mmap.mmap):
def read_byte(self):
return ord(super(memmap,self).read_byte())
Создайте класс, который наследует класс mmap и перезаписывает read_byte по умолчанию, который возвращает строку длиной от 1 до единицы, которая возвращает int. И тогда вы можете использовать этот класс как любой другой класс mmap.
Надеюсь, это поможет.