문제

최근에 물었다 파이썬에서 파일 슬러프를 수행하는 방법, 그리고 받아 들여진 답변은 다음과 같은 것을 제안했습니다.

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

파일을 읽고 데이터의 엔디언 표현을 변환하기 위해이 작업을 수행하는 방법은 무엇입니까?

예를 들어, 나는 Big Endian으로 포장 된 단일 정밀도의 1GB 바이너리 파일을 가지고 있으며 Little Endian으로 변환하여 멍청한 배열로 덤프하고 싶습니다. 아래는 내가 이것을 달성하기 위해 쓴 기능과 그것을 부르는 실제 코드입니다. 나는 사용한다 struct.unpack Endian 변환을 수행하고 mmap.

내 질문은, 내가 슬러프를 올바르게 사용하고 있습니까? 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)
도움이 되었습니까?

해결책

with open(fileName, "rb") as f:
  arrayName = numpy.fromfile(f, numpy.float32)
arrayName.byteswap(True)

속도와 간결함을 위해 이길 수는 매우 어렵다 ;-). 바이트 웨이프를 참조하십시오 여기 (그만큼 True 인수는 "제자리에 그것을하십시오"); Fromfile을 참조하십시오 여기.

이것은 Little-Endian 머신에서와 같이 작동합니다 (데이터는 Big-Endian이므로 바이트 웨이프가 필요합니다). 바이트 웨이프를 조건부로 수행하는 경우를 테스트 할 수 있으며, 마지막 줄을 무조건 호출에서 바이트 웨이로 변경하여 다음과 같습니다.

if struct.pack('=f', 2.3) == struct.pack('<f', 2.3):
  arrayName.byteswap(True)

즉, 작은 목록 테스트에서 조건부 조건부에 대한 호출.

다른 팁

약간 수정되었습니다 @Alex Martelli의 대답:

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

당신은 함께 코블을 할 수 있습니다 ASM 기반 솔루션 사용 핵심. 하지만 알고리즘의 다른 부분에서 충분한 성능을 얻을 수 있는지 궁금합니다. 1GB의 데이터 덩어리에 대한 I/O 및 조작에는 시간이 걸릴 것입니다.

도움이 될 수있는 또 다른 점은 Python에서 알고리즘을 프로토 타입 한 후에 C로 전환하는 것입니다. 전체 세계 DEM (높이) 데이터 세트에서 한 번 조작하기 위해이 작업을 수행했습니다. 해석 된 스크립트에서 멀어지면 모든 것이 훨씬 더 견딜 수있었습니다.

나는 이런 것이 더 빨라질 것으로 기대합니다

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

사용하지 마십시오 map 변수 이름으로

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top