Seite 1 von 2
ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 15:16
von Pf@nne
Moin,
ich muss einer fertigen Function (SPI.writebytes auf meinem Rasperry Pi) eine Liste mit Integerwerten übergeben.
Diese Integerliste darf/kann nicht mehr als 4096 Werte aufnehmen.
Die "Füllung" stammt aus einem File (GrafikFile mit Farbwerten pro Pixel).
Mit:
Code: Alles auswählen
def get_bytes_from_file(filename):
return open(filename, "rb").read()
def GetFileList(filename):
FileData = get_bytes_from_file("75x108.bin")
print FileData
hole ich die einzelnen Bytes in ein Array.....
Das klappt auch soweit......
Wie bekomme ich jetzt die Bytes aus FileData Blockweise (4096) in eine IntegerListe?
Gruß
Pf@nne
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 16:11
von Sirius3
@Pf@nne: was ist eine IntegerListe? wie wäre es wenn Du jeweils Blöcke von 4096 Bytes lesen würdest?
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 16:51
von Pf@nne
Der SPI.WriteBytes-Befehl möchte eine Liste von Integerwerten [1, 255, 43, ...]
Blöcke lesen wäre OK, ich hab bloß noch nicht verstanden wie ich die gelesenen Daten in das o.g. Format bekomme.....
Gruß
Pf@nne
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 17:00
von BlackJack
@Pf@nne: Musst Du denn da überhaupt irgend etwas konvertieren? Ein `bytearray` sollte es doch eigentlich auch tun.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 17:28
von Pf@nne
Code: Alles auswählen
spi.writebytes(FileData[0:100])
TypeError: Argument must be a list of at least one, but not more than 4096 integers
Der will immer eine Liste haben.....
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 17:30
von BlackJack
@Pf@nne: Einfach `list()` drauf aufrufen sollte es tun.
Wirf mal einen Blick in den
Style Guide for Python Code bezüglich der Namensgebung. Bei `FileData` denkt ein Python-Programmierer es handelt sich um einen Datentyp.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 18:18
von Pf@nne
Code: Alles auswählen
spi.writebytes(list(FileData[0:100]))
TypeError: Argument must be a list of at least one, but not more than 4096 integers
List() liefert scheinbar Strings (Chars).....
['\xd6', 'x', '\xd6', '\x98', '\xd6', 'W', '\x9c', 'n', '\x8b', '\xcc', '\x83', '\xac', '\x83', '\x8b', '{', 'J', '{', ')', '{', 'I', '{', 'I', '{', 'I', '\x83', 'j', '\x83', 'j', '\x83', 'j', '\x83', '\x8a', '\x83', '\x8a', '\x83', '\x8b', '\x8b', '\xab', '\x83', '\xab', '\x8b', '\xcb', '\xa4', '\xb1', '\x9c', '\xb1', 'I', '\xc5', '(', '\xe2', '(', '\xe2', '0', '\xe2', '0', '\xe2', '0', '\xe2', '0', '\xe2', '1', '\x02', '1', '\x02', '1', '\x02', '1', '\x02', 'Z', 'h', '\xc5', '\xd5', '\xd6', '7', '\xde', '\x99', '\xde', '\xb9', '\xe6', '\xb9', '\xe6', '\xb9', '\xe6', '\xb9', '\xe6', '\xda', '\xee', '\xda', '\xee', '\xfa', '\xe6', '\xba', '\xde', 'x', '\xd6', 'W', '\xd6', '7', '\xd6', '7']
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 18:24
von BlackJack
@Pf@nne: Dann war `FileData` aber auch nicht wie im Betreff vom dem Thema angedeutet ein `bytearray`. Lösung: Es zu einem machen, oder die ”Zeichen” mit der `ord()`-Funktion umwandeln.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 20:00
von Pf@nne
OK, anders gefragt,
wie bekomme ich die einzelnen Bytes eines Files in eine Liste?
Code: Alles auswählen
with open("75x108.bin", 'rb') as f:
f.read(0xFFF)
print list(f)
Da kommen auch "nur" Strings raus......
Jedes Zeichen mit Ord() würde gehen, es muss doch aber auch einen "direkten" weg geben.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 20:20
von BlackJack
@Pf@nne: Offensichtlich will die Funktion eine Liste mit `int`-Objekten haben. Also muss man eine Liste mit `int`-Objekten erstellen. Was sollte da direkter sein als die Bytewerte mit `ord()` in die entsprechenden `int`-Objekte umzuwandeln? Ist ja auch nicht wirklich aufwändig das mit `map()` auf die Zeichenkette anzuwenden.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 21:00
von Pf@nne
Was sollte da direkter sein als die Bytewerte mit `ord()` in die entsprechenden `int`-Objekte umzuwandeln?
Ich hätte jetzt gesagt, dass die Bytewerte auch als solche ausgelesen werden.
Ein Byte liegt doch im File in der Form BIN[1010_1010] = HEX[AA] = DEC[170] vor, die Zeichenfolge "¬" bzw "\xaa" ist dch schon durch eine Routine gelaufen (Prüfung auf darstellbaren ASCII-Wert).
Ist ja auch nicht wirklich aufwändig das mit `map()` auf die Zeichenkette anzuwenden.
Ich mache es jetzt so:
Code: Alles auswählen
DataRead = f.read(0xFFF)
print map(ord, list(DataRead))
Danke für die Unterstützung....
Gruß
Pf@nne
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 21:12
von BlackJack
@Pf@nne: Die Methode will ja offenbar unbedingt eine Liste mit `int`-Objekten haben, also muss man ihr auch genau das geben. Und *das* wird ja nicht eingelesen, sondern eine Bytekette als `str`-Datentyp. Die Prüfung auf darstellbare ASCII-Zeichen passiert nur bei der Ausgabe der Liste mit den Zeichenketten, eigentlich Byteketten, mit jeweils einem Zeichen, eigenlich Byte.
Die `list()`-Aufruf ist ein unnötiger Zwischenschritt.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 21:19
von darktrym
Könnte man sicher schöner mit struct.unpack lösen.
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 21:26
von Pf@nne
OK,
hab ich einigermaßen verstanden...
Code: Alles auswählen
with open("75x108.bin", 'rb') as f:
FileSize = os.path.getsize("75x108.bin")
DataBuffer=[]
while (FileSize > 0):
if FileSize > 0xFFF:
DataBuffer.append(f.read(0xFFF))
FileSize = FileSize - 0xFFF
else:
DataBuffer.append(f.read(FileSize))
FileSize = 0
for i in range(0, len(DataBuffer)):
print "SPI_Data",i
print map(ord, DataBuffer[i])
#Write SPI_int_List here.......
oder kann man das noch einfacher (schneller) gestalten, je schneller das lesen und Bereitstellen der 4k-Blöcke läuft,
desto schneller wird mein Bild aufgebaut......
Daher wäre eine Optimierung von Vorteil....
Gruß
Pf@nne
Re: ByteArray to IntegerList
Verfasst: Sonntag 13. April 2014, 21:37
von BlackJack
@darktrym: In wie weit „schöner”? Bei ``map(ord, data)`` vs. ``list(struct.unpack('{0}b'.format(len(data)), data))`` oder ``list(struct.unpack('b' * len(data), data))`` gewinnt für mich die `map()`-Lösung den Schönheitswettbewerb.
@Pf@nne: Das mit `FileSize` ist unnötig. Einfach so lange 0xfff grosse Blöcke lesen bis die leere Zeichenkette als Abbruchbedingung kommt.
Die ``for``-Schleife über einen Index ist in Python ein „anti pattern”, Du kannst doch *direkt* über die Elemente iterieren. Falls man *zusätzlich* noch einen Index braucht, gibt es die `enumerate()`-Funktion.
Ich würde aber direkt einen Iterator über die Datenblöcke basteln und die gar nicht erst in eine Liste stecken. Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python
from functools import partial
def main():
with open('75x108.bin', 'rb') as image_file:
for data in iter(partial(image_file.read, 0xfff), ''):
print map(ord, data)
if __name__ == '__main__':
main()
Re: ByteArray to IntegerList
Verfasst: Montag 14. April 2014, 04:39
von darktrym
Spät. wenn du den gleichen Ausdruck unter Python3 ausführst bekommst du ein Problem weil dann ord eine Exception auslöst wird.
Re: ByteArray to IntegerList
Verfasst: Montag 14. April 2014, 10:07
von BlackJack
@darktrym: Und? Hier geht es um Python 2, erkennbar an der ``print``-Anweisung im Quelltext vom OP. Und unter Python 3 bekommt man von dem `read()` ein `bytes`-Objekt wo man einfach ``list(data)`` aufruft. Da wäre etwas mit `struct` noch umständlicher im Vergleich.
Re: ByteArray to IntegerList
Verfasst: Montag 14. April 2014, 16:49
von Pf@nne
Hi,
der Vorschlag von BlackJack läuft einwandfrei......
Code: Alles auswählen
from functools import partial
with open('75x108.bin', 'rb') as image_file:
WriteCMD(0x02)
GPIO.output(8, False)
spi.writebytes([0x00]) #WriteData Byte
image_file.seek(40) #HeaderOffset
for data in iter(partial(image_file.read, 0xfff), ''):
spi.writebytes(map(ord, data))
GPIO.output(8, True)
Vielen Dank......
Re: ByteArray to IntegerList
Verfasst: Montag 14. April 2014, 20:12
von darktrym
BlackJack hat geschrieben:@darktrym: Und? Hier geht es um Python 2, erkennbar an der ``print``-Anweisung im Quelltext vom OP. Und unter Python 3 bekommt man von dem `read()` ein `bytes`-Objekt wo man einfach ``list(data)`` aufruft. Da wäre etwas mit `struct` noch umständlicher im Vergleich.
Da hier Raspberry auf einem Linux läuft mit einen in die Jahre gekommenen Python Version, willst du 2014 immer noch Lösungen propagieren die nur auf diese laufen? Umständlicher wäre es ein zweites Mal den gleichen Code anzurühren nur weil man heute zu faul war daran zu denken.
Re: ByteArray to IntegerList
Verfasst: Montag 14. April 2014, 20:26
von BlackJack
@darktrym: Du würdest dann also lieber diesen `struct`-Unsinn machen weil das auf beiden Versionen umständlich ist, mit der Begründung das wäre ”schöner”? Ich bin weder zu faul an eine Python-Version zu denken die sich *immer noch nicht* durchgesetzt hat, noch das umzuschreiben, sollte es doch keine Totgeburt sein.

Oh, und wenn man eine Version schreiben möchte die unter beiden Versionen läuft, gibt es eine offensichtliche Lösung ohne `struct` die schöner, weil weniger umständlich ist. Die hatte ich auch schon angesprochen.