Frage

Es wurde vor kurzem gefragt , wie eine Datei schlürft in Python zu tun, und die akzeptierte Antwort vorgeschlagen etwas wie:

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

Wie würde ich mich dies zu tun, um die Datei in und wandelt die Endian-Darstellung der Daten zu lesen?

Zum Beispiel habe ich eine 1 GB binäre Datei, die als Big-Endian verpackt nur ein Haufen einfacher Genauigkeit Schwimmer ist und ich mag es wenig Endian konvertieren und Dump in eine numpy Array. Unten ist die Funktion, die ich dieses und einige echte Code zu erreichen, schrieb, die es nennt. Ich benutze struct.unpack die Endian-Umwandlung tun und versucht, alles zu beschleunigen, indem mmap verwendet wird.

Meine Frage ist dann, verwende ich die slurp richtig mit mmap und struct.unpack? Gibt es eine sauberen, schnellen Weg, dies zu tun? Gerade jetzt, was ich habe funktioniert, aber ich würde wirklich lernen, wie man dies besser zu tun.

Vielen Dank im Voraus!

#!/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)
War es hilfreich?

Lösung

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

Ziemlich schwer für Geschwindigkeit und Prägnanz zu schlagen ;-). Für byteswap siehe hier (das True Argument bedeutet, "es an Ort und Stelle zu tun"); siehe hier .

Das funktioniert wie auf dem Little-Endian-Maschinen ist (da die Daten Big-Endian sind, wird die byteswap erforderlich). Sie können testen, ob das der Fall ist, die byteswap bedingt, ändern Sie die letzte Zeile von einem unbedingten Aufruf zu tun in byteswap, zum Beispiel:

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

d., Ein Anruf auf einen Test von little-Endian-bedingte byteswap.

Andere Tipps

Leicht modifizierte @ Alex Martelli Antwort :

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

Sie könnten Coble zusammen ein ASM-basierte Lösung mit CorePy . Ich frage mich aber, wenn Sie genug Leistung aus dem einem anderen Teil des Algorithmus zu gewinnen möglicherweise in der Lage. I / O und Manipulationen auf 1 GB Datenblöcke werden eine Weile dauern, die jemals, wie Sie es.

Eine andere Sache, die Sie hilfreich finden könnten wäre zu C wechseln, sobald Sie den Algorithmus in Python prototypisiert haben. Ich tue dies für Manipulationen auf einer ganze Welt DES (Höhe) Datensatz einmal. Das Ganze war viel erträglicher, wenn ich aus dem interpretierten Skript entkam.

Ich würde so etwas wie dies erwartet, schneller sein

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

Bitte verwenden Sie keine map als Variablenname

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top