Каков наиболее эффективный способ чтения большого двоичного файла python

У меня есть большой (21 ГБ) файл, который я хочу прочитать в памяти, а затем передать подпрограмме, которая прозрачно для меня обрабатывает данные. Я использую python 2.6.6 на Centos 6.5, поэтому обновление операционной системы или python не вариант. В настоящее время я использую

f = open(image_filename, "rb")
image_file_contents=f.read()
f.close()
transparent_subroutine ( image_file_contents )

что медленно (~ 15 минут). Прежде чем я начну читать файл, я знаю, насколько он велик, потому что я вызываю os.stat(image_filename).st_size

поэтому я мог бы предварительно выделить немного памяти, если бы это имело смысл.

Спасибо


person Jeff Silverman    schedule 09.09.2014    source источник
comment
Используйте 1_. docs.python.org/3/library/mmap.html   -  person Dietrich Epp    schedule 10.09.2014
comment
Больший буфер может помочь open(image_filename, 'rb', 64*1024*1024)   -  person tdelaney    schedule 10.09.2014
comment
Как вы планируете получать доступ к данным? Случайный доступ? Прочитать блок, обработать, повторить? Или вам действительно нужно, чтобы весь файл отображался в памяти?   -  person xavier    schedule 10.09.2014
comment
Я не знаю, как осуществляется доступ к данным. Это входные данные для просмотра программы openstack, которая использует его для создания тома. Я не пытался изменить размер буфера, это умно.   -  person Jeff Silverman    schedule 12.09.2014


Ответы (2)


Следуя предложению Дитриха, я замерил, что этот метод mmap на 20% быстрее, чем одно большое чтение для входного файла размером 1,7 ГБ.

from zlib import adler32 as compute_cc

n_chunk = 1024**2
crc = 0
with open( fn ) as f:
  mm = mmap.mmap( f.fileno(), 0, prot = mmap.PROT_READ, flags = mmap.MAP_PRIVATE )
  while True:
    buf = mm.read( n_chunk )
    if not buf: break
    crc = compute_crc( buf, crc )
return crc
person FDS    schedule 20.03.2015

с помощью генератора

def generator(file_location):

    with open(file_location, 'rb') as entry:

        for chunk in iter(lambda: entry.read(1024 * 8), b''):

            yield chunk


go_to_streaming = generator(file_location) 
person sandes    schedule 16.04.2020