Вопрос

Недавно был задан вопрос о том, как сделать файловую ошибку в python , и принятый ответ предложил что-то как:

with open('x.txt') as x: f = x.read()

Как мне поступить так, чтобы прочитать файл и преобразовать представление данных в обратном порядке?

Например, у меня есть двоичный файл объемом 1 ГБ, представляющий собой просто набор чисел с плавающей запятой одинарной точности, упакованный в формате с прямым порядком байтов, и я хочу преобразовать его в формат с прямым порядком байтов и вывести в массив Numpy. Ниже приведена функция, которую я написал для выполнения этого и некоторый реальный код, который ее вызывает. Я использую struct.unpack для преобразования в обратный порядок и пытался ускорить все, используя mmap .

Тогда у меня вопрос: правильно ли я использую slurp с mmap и struct.unpack ? Есть ли более чистый и быстрый способ сделать это? Сейчас то, что у меня работает, но я бы очень хотел узнать, как это сделать лучше.

Заранее спасибо!

#!/usr/bin/python
from struct import unpack
import mmap
import numpy as np

def mmapChannel(arrayName,  fileName,  channelNo,  line_count,  sample_count):
    """
    We need to read in the asf internal file and convert it into a numpy array.
    It is stored as a single row, and is binary. Thenumber of lines (rows), samples (columns),
    and channels all come from the .meta text file
    Also, internal format files are packed big endian, but most systems use little endian, so we need
    to make that conversion as well.
    Memory mapping seemed to improve the ingestion speed a bit
    """
    # memory-map the file, size 0 means whole file
    # length = line_count * sample_count * arrayName.itemsize
    print "\tMemory Mapping..."
    with open(fileName, "rb") as f:
        map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
        map.seek(channelNo*line_count*sample_count*arrayName.itemsize)

        for i in xrange(line_count*sample_count):
            arrayName[0, i] = unpack('>f', map.read(arrayName.itemsize) )[0]

        # Same method as above, just more verbose for the maintenance programmer.
        #        for i in xrange(line_count*sample_count): #row
        #            be_float = map.read(arrayName.itemsize) # arrayName.itemsize should be 4 for float32
        #            le_float = unpack('>f', be_float)[0] # > for big endian, < for little endian
        #            arrayName[0, i]= le_float

        map.close()
    return arrayName

print "Initializing the Amp HH HV, and Phase HH HV arrays..."
HHamp = np.ones((1,  line_count*sample_count),  dtype='float32')
HHphase = np.ones((1,  line_count*sample_count),  dtype='float32')
HVamp = np.ones((1,  line_count*sample_count),  dtype='float32')
HVphase = np.ones((1,  line_count*sample_count),  dtype='float32')



print "Ingesting HH_Amp..."
HHamp = mmapChannel(HHamp, 'ALPSRP042301700-P1.1__A.img',  0,  line_count,  sample_count)
print "Ingesting HH_phase..."
HHphase = mmapChannel(HHphase, 'ALPSRP042301700-P1.1__A.img',  1,  line_count,  sample_count)
print "Ingesting HV_AMP..."
HVamp = mmapChannel(HVamp, 'ALPSRP042301700-P1.1__A.img',  2,  line_count,  sample_count)
print "Ingesting HV_phase..."
HVphase = mmapChannel(HVphase, 'ALPSRP042301700-P1.1__A.img',  3,  line_count,  sample_count)

print "Reshaping...."
HHamp_orig = HHamp.reshape(line_count, -1)
HHphase_orig = HHphase.reshape(line_count, -1)
HVamp_orig = HVamp.reshape(line_count, -1)
HVphase_orig = HVphase.reshape(line_count, -1)
Это было полезно?

Другие советы

Слегка измененный @Alex Martelli's answer :

arr = numpy.fromfile(filename, numpy.dtype('>f4'))
# no byteswap is needed regardless of endianess of the machine

Вы можете объединить решение на основе ASM , используя CorePy . Интересно, если бы вы могли получить достаточно производительности от какой-то другой части вашего алгоритма. Операции ввода-вывода и манипуляции с кусками данных объемом 1 ГБ будут занимать какое-то время, как бы вы их ни разрезали.

Еще одна вещь, которая может оказаться для вас полезной, - переключиться на C после того, как вы создали прототип алгоритма в python. Я сделал это для манипуляций с набором данных DEM (высота) всего мира один раз. Все это стало гораздо более терпимым, когда я ушел от интерпретированного сценария.

Я бы ожидал, что что-то вроде этого будет быстрее

arrayName[0] = unpack('>'+'f'*line_count*sample_count, map.read(arrayName.itemsize*line_count*sample_count))

Пожалуйста, не используйте map в качестве имени переменной

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top