Wie Rohr binären Daten in numpy-arrays ohne tmp-Speicher?
Gibt es mehrere ähnliche Fragen, aber keiner von Ihnen beantwortet diese einfache Frage direkt:
Wie kann ich catch a-Befehle output und Streams, die Inhalte in numpy-arrays ohne erstellen eines temporären string-Objekt zum Lesen aus?
So, was ich tun möchte, ist dies:
import subprocess
import numpy
import StringIO
def parse_header(fileobject):
# this function moves the filepointer and returns a dictionary
d = do_some_parsing(fileobject)
return d
sio = StringIO.StringIO(subprocess.check_output(cmd))
d = parse_header(sio)
# now the file pointer is at the start of data, parse_header takes care of that.
# ALL of the data is now available in the next line of sio
dt = numpy.dtype([(key, 'f8') for key in d.keys()])
# i don't know how do make this work:
data = numpy.fromxxxx(sio , dt)
# if i would do this, I create another copy besides the StringIO object, don't I?
# so this works, but isn't this 'bad' ?
datastring = sio.read()
data = numpy.fromstring(datastring, dtype=dt)
Versuchte ich es mit StringIO und cStringIO aber beide werden nicht akzeptiert, von numpy.frombuffer und numpy.fromfile.
Mit StringIO-Objekt, die ich zuerst Lesen müssen, um den stream in einen string und verwenden Sie dann numpy.fromstring, aber ich möchte vermeiden, erstellen die Mittelstufe-Objekt (mehrere Gigabyte).
Alternative für mich wäre, wenn ich stream sys.stdin in numpy-arrays, aber das funktioniert nicht mit numpy.fromfile entweder (suchen muss umgesetzt werden).
Gibt es irgendwelche Workarounds für diese? Ich kann nicht die erste sein, die dies versuchen, (es sei denn, dies ist ein PEBKAC Fall?)
Lösung:
Dies ist die aktuelle Lösung, es ist eine Mischung aus unutbu Anleitung wie die Popen, die mit PFEIFE und den Hauch von eryksun zu verwenden bytearray, also ich weiß nicht, wer zu akzeptieren!? :S
proc = sp.Popen(cmd, stdout = sp.PIPE, shell=True)
d = parse_des_header(proc.stdout)
rec_dtype = np.dtype([(key,'f8') for key in d.keys()])
data = bytearray(proc.stdout.read())
ndata = np.frombuffer(data, dtype = rec_dtype)
Ich nicht prüfen, ob die Daten wirklich nicht das erstellen einer weiteren Kopie nicht wissen, wie. Was ich aber bemerkt, dass dies funktioniert viel schneller, als alles was ich vorher versucht, also vielen Dank an beide Antworten " Autoren!
- Haben Sie als numpy.fromiter?
- Könnte Sie post ein (Vereinfachtes) Beispiel, welche Art von Funktion (oder-Eingang) beschäftigen wir uns mit?
- getan, mehr klar jetzt?
- Vielleicht verwenden
Popen
mitstdout=subprocess.PIPE
(d.h. keine temporären string mitcheck_output
), Lesen Sie in der Kopfzeile, dann laden Sie den rest in einebytearray
zu verwenden mitnp.frombuffer
. Die NumPy-array teilen sich den gleichen Speicher wie diebytearray
. - Ihre Methode funktioniert, @eryksun. legen Sie es in eine Antwort zu bekommen, einige Akzeptanzstellen. 😉
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie
Popen
mitstdout=subprocess.PIPE
. Lesen Sie in der Kopfzeile, dann laden Sie den rest in einebytearray
zu verwenden mitnp.frombuffer
.Zusätzliche Kommentare nach deinem edit:
Wenn du gehst zu nennen
proc.stdout.read()
, es ist gleichbedeutend mitcheck_output()
. Beide erstellen Sie einen temporären string. Wenn Sie preallocatedata
könnten Sieproc.stdout.readinto(data)
. Dann, wenn die Anzahl der gelesenen bytes indata
ist weniger alslen(data)
, befreien Sie den überschüssigen Speicher, sonst verlängerndata
von was auch immer übrig ist, um zu Lesen.Könnten Sie nicht auch kommen an dieser beginnend mit einer pre-allocated
ndarray
ndata
und verwendenbuf = np.getbuffer(ndata)
. Dannreadinto(buf)
wie oben.Hier ist ein Beispiel, um zu zeigen, dass der Speicher freigegeben, zwischen den
bytearray
und dienp.ndarray
:Da Ihre Daten können leicht in den Arbeitsspeicher passen, ich denke, der einfachste Weg, um zum laden der Daten in ein numpy-array ist die Verwendung eines ramfs.
Unter Linux,
Dann zum Beispiel, wenn dies der Hersteller der binären Daten:
writer.py:
Dann könnten Sie laden Sie Sie in ein numpy-array wie dieses:
reader.py:
fromiter
hat einecount
Schlagwort (überprüfen Sie die docstring). Wenn Sie es nicht verwenden, wird das array verkleinert, wie es gebaut ist. Sie könnte immer noch das problem der zeitweise mit sehr viel mehr Speicher als die endgültige Größe des Arrays.count
parameter ist in diesem Fall, weil wir nicht wissen, wie viele Zeilen von Daten werden ausgegeben, indem der Prozess.iter(readline, "")
gibt einen iterator, welches die Folge vonreadline()
bis es den Wert erreicht, den""
. So ist es nur ein Weg, um Zuleitungen zuprocess_data
. Nun, ich verstehe das problem, das nutzlos ist 🙂cmd
? Können es alle in den Arbeitsspeicher passen? Wenn ja, könnten Sie vielleicht eine ramfs, leiten die Ausgabe in eine Datei im ramfs, und verwenden Sie dannnp.fromfile
laden Sie ein numpy-array...