Hallo Leute,
ich stehe gerade voll auf dem Schlauch :-/
Folgende Gesichte:
Ich moechte mit einem Python-Script Binaerdaten einlesen und
entsprechend interpretieren.
Als Beispiel koennte man hier den Header einer BMP-Datei nehmen:
https://de.wikipedia.org/wiki/Windows_Bitmap
Dort gibt es Felder die als signed oder unsigned interpetiert werden
sollten.
Und jetzt meine Frage: Wie mach ich denn sowas in Python?
Nehmen wir einfach mal als Beispiel das Datum: 0xFFFF
Jetzt kann ich sowas machen:
1
#!/usr/bin/env python
2
3
importstruct
4
5
defmain():
6
x=struct.unpack('h',struct.pack('H',0xFFFF))[0]
7
y=struct.unpack('H',struct.pack('H',0xFFFF))[0]
8
print('x = {0} | y = {1}'.format(x,y))
9
10
11
if__name__=='_main__':
12
main()
Dann ist x = -1 und y = 65535. Soweit sogut.
Aber ich finde diese Loesung mega haesslich und umstaendlich.
Gibt es da was einfacheres/schoeneres?
Gruesse
Sollte das in Python nicht einfach zu machen sein, dann wäre es legitim
die Frage zu stellen, ob man an der Stelle nicht eine andere
Programmiersprache verwenden sollte.
Der Grundsatz ist immer: Wähle ein Werkzeug, das zur Aufgabenstellung
passt.
Kaj G. schrieb:> x = struct.unpack(fmt, data)> Aber ich finde diese Loesung mega haesslich und umstaendlich.
was ist daran hässlich? Eleganter und einfacher gehts doch kaum noch?
Florian F. schrieb:> und struct.unpack aliast
Eeh, dadurch wird der Code definitiv viel lesbarer. Nicht.
Nein, eine bessere Lösung als mit struct gibt es m.W. nicht, aber wie
schon gesagt wurde ist das doch auch ganz in Ordnung. Wie stellst du es
dir denn vor?
Mark B. schrieb:> Sollte das in Python nicht einfach zu machen sein, dann wäre es legitim> die Frage zu stellen, ob man an der Stelle nicht eine andere> Programmiersprache verwenden sollte.
Ich kenne keine Programmiersprache, in der das Extrahieren von Integer-
und Floating-Point-Zahlen, Zeichen und Strings bei gemischten Datentypen
auf portable Weise einfacher ginge als in Python.
Kaj G. schrieb:> Als Beispiel koennte man hier den Header einer BMP-Datei nehmen:> https://de.wikipedia.org/wiki/Windows_Bitmap
So geht's:
Hier werden alle Elemente des 54-Byte-Headers einzelnen Variablen
zugewisen, wobei bfReserved übersprungen wird, weil es nicht von
Interesse ist. Selbst in C tippt man dafür deutlich mehr Code.
Die Funktionen struct.pack und struct.unpack sind sozusagen das sprintf
und sscanf für Binärdaten.
Okay, wie so oft: Das Problem sitzt vor dem Monitor :-/
Mein Problem bestand darin, dass ich die Daten zusammen geshiftet hatte:
1
f = open(dateiname, 'rb')
2
fc = f.read()
3
4
x = (fc[1] << 8) | fc[0]
Damit war es kein Byte-Object mehr, und deswegen geht das nicht direkt
mit struct.unpack, sondern nur ueber den umweg mit
struct.unpack(struct.pack(...)).
Lass ich dass mit der Shifterei funktioniert es direkt mit
struct.unpack.
Damit gefaellt mir das auch schon viel besser :)
Danke euch.
Es gaebe wohl noch die Moeglichkeit mit ctypes:
1
import ctypes
2
3
f = open(dateiname, 'rb')
4
fc = f.read()
5
6
x = ctypes.c_int16((fc[1] << 8) | fc[0])
Aber die ctypes bringen wieder andere Probleme mit sich.
Tja, kaum hat man drueber gesprochen, loest sich dass Problem wie von
selbst. :)
Yalu X. schrieb:> So geht's:
...ist mir zu kryptisch :(
Ich mach es mir dann doch etwas aufwaendiger:
Aber das ist geschmackssache.
Was mich gestoert hatte, war die verschachtelung von
struct.unpack(struct.pack(...)), die aber nur noetig war, weil ich die
Daten von Hand zusammengeshiftet hatte.
Naja, Problem erkannt, Problem gebannt. :)
Yalu X. schrieb:> Ich kenne keine Programmiersprache, in der das Extrahieren von Integer-> und Floating-Point-Zahlen, Zeichen und Strings bei gemischten Datentypen> auf portable Weise einfacher ginge als in Python.
Vielleicht habe ich den Threadersteller ja falsch verstanden. Ging es
ausschließlich um das Extrahieren, oder darum wie man im weiteren
Verlauf mit den Daten umgeht? Nach meinem Verständis behandelt Python
bei arithmetischen Operationen eine Ganzzahl immer als
vorzeichenbehaftet. Korrigier mich gerne wenn ich falsch liege.
Mark B. schrieb:> Vielleicht habe ich den Threadersteller ja falsch verstanden. Ging es> ausschließlich um das Extrahieren, oder darum wie man im weiteren> Verlauf mit den Daten umgeht?
IMHO ersteres, aber genau weiß es nur Kaj ;-)
> Nach meinem Verständis behandelt Python bei arithmetischen Operationen> eine Ganzzahl immer als vorzeichenbehaftet. Korrigier mich gerne wenn> ich falsch liege
Richtig. Wobei das normalerweise kein Problem ist, da es in Python keine
Integer-Überläufe gibt.
Besonders elegant ist bei Python natürlich auch die Behandlung der
Endianess gelöst. Man gibt in der Formatangabe bei struct.pack bzw
struct.unpack einfach einen Endianess-Qualifizierer an, siehe:
https://docs.python.org/3/library/struct.html#struct.calcsize
Die Endianess des Systems, auf dem ein Programm läuft, lässt sich auch
direkt per sys.byteorder bestimmen.