/ / Schreibe eine Zeichenkette aus maskierten Byte-Zeichen, zB 'x00x20 ...', als wären sie Bytes - Python, Python-2.7

Schreibe eine Folge von maskierten Byte-Zeichen, zB 'x00x20 ...', als wären sie Bytes - Python, Python-2.7

Ich spiele damit herum.WAV-Datei-Generierung und Funktionen zur Umwandlung von Basis 10 Integer in Hexadezimal. Ich muss diese hexadezimalen Zahlen so schreiben, als ob sie Bytes wären, nicht einfach, um sie als Bytes zu schreiben. Ich kann Code mit Escape-Sequenzen hart codieren, aber ich muss Zeichenfolgen verwenden, die von meinen Funktionen bereitgestellt werden.

Meine temporäre Arbeit nutzt Eval wie folgt.

eval("b"" + endian(bytestring(tohex(16, 32))) + """)

Was ist eine bevorzugte Methode, um diese Aufgabe ohne Eval zu erreichen?

Hier ist ein Code, um die Situation besser zu verstehen.

with open("song.wav", "wb") as f:
f.write(ChunkID)
f.write(ChunkSize)
f.write(Format)
f.write(Subchunk1ID)
f.write(Subchunk1Size)
f.write(AudioFormat)
f.write(NumChannels)
f.write(SampleRate)
f.write(ByteRate)
f.write(BlockAlign)
f.write(BitsPerSample)
f.write(Subchunk2ID)
f.write(Subchunk2Size)
f.write(Data)

Die Verwendung fest codierter Werte funktioniert gut.

ChunkID = b"RIFF"               #big        1
ChunkSize = b"x1axeaxc4x00"     #little     2
Format = b"WAVE"                #big        3
Subchunk1ID = b"fmt "               #big        4
Subchunk1Size = b"x10x00x00x00"         #little     5
AudioFormat = b"x01x00"           #little     6
NumChannels = b"x02x00"           #little     7
SampleRate = b"x22x56x00x00"        #little     8
ByteRate = b"x88x58x01x00"          #little     9
BlockAlign = b"x04x00"            #little     10
BitsPerSample = b"x10x00"         #little     11
Subchunk2ID = b"data"               #big        12
Subchunk2Size = b"x10xb1x02x00"     #little     13
Data = b""                  #little     14

Ich brauche mehr Flexibilität und brauche ähnliche Ergebnisse mit Funktionen.

def tohex(val, nbits):
a = hex((val + (1 << nbits)) % (1 << nbits))
pad = nbits/4 - (len(a) - 2)
for i in range(0, pad):
a = a[:2] + "0" + a[2:]
return a
def bytestring(hexstring):
hexstring = hexstring[2:]
bstring = ""
for i in range(0, len(hexstring)/2):
bstring += "\x"
bstring += hexstring[2*i: 2*i+2]
return bstring
def endian(bstring):
return "\"+"\".join(reversed(bstring.split("\"))).rstrip("\")

So rufe ich die Funktionen auf

sample_rate = 44100
channels = 2
sample_bits = 16
sample_count = 176400

ChunkID = b"RIFF"
Format = b"WAVE"
Subchunk1ID = b"fmt "
Subchunk1Size = eval("b"" + endian(bytestring(tohex(16, 32))) + """)    #n bit samples : tohex(n,m)
AudioFormat = eval("b"" + endian(bytestring(tohex(1, 16))) + """)       #uncompressed when n=1
NumChannels = eval("b"" + endian(bytestring(tohex(channels, 16))) + """)        #n channels
SampleRate = eval("b"" + endian(bytestring(tohex(sample_rate, 32))) + """)
BitsPerSample = eval("b"" + endian(bytestring(tohex(sample_bits, 16))) + """)
ByteRate = eval("b"" +  endian(bytestring(tohex(sample_rate*channels*sample_bits/8, 32))) + """)
BlockAlign = eval("b"" + endian(bytestring(tohex(channels*sample_bits/8, 16))) + """)
Subchunk2ID = b"data"
Subchunk2Size = eval("b"" + endian(bytestring(tohex(sample_count*channels*sample_bits/8, 32))) + """)
ChunkSize = eval("b"" + endian(bytestring(tohex(36 + sample_count*channels*sample_bits/8, 32))) + """)
Data = b""

for i in range(0, 176400): #Just test samples
if i % 32 < 16:
Data += b"x10xe7x10xe7"
else:
Data += b"xf0xa8xf0xa8"

Update: Ich habe eine neue Funktion hinzugefügt, um die vorherige Formatierung zu behandeln und ein Formular zurückzusenden, das ich direkt in die Datei schreiben kann. Die Lösung, die ich markiert habe, verwendet Bytes, aber in Python 2.7 musste ich Bytearray verwenden.

def barray(bstring):
hexmap = {"0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7,"8":8, "9":9, "a":10, "b":11, "c":12, "d":13, "e":14, "f":15}
bstring = bstring.lstrip("\x")
bstring = bstring.split("\x")
bstring = map(lambda x: 16*hexmap[x[0]]+hexmap[x[1]], bstring)
return bytearray(bstring)

Jetzt, nachdem ich die Funktionen aufgerufen habe, sind die Daten bereit, in die Datei zu schreiben, ohne eval () zu verwenden.

variable = barray(endian(bytestring(tohex(n, m))))

Antworten:

1 für die Antwort № 1

Hast du es versucht? bytes?

data = "x00x20x10"
newdata = [int(i) for i in data.encode()]
print(newdata)
>>> [0, 32, 16]
print(bytes(newdata))
>>> b"x00 x10"  # it only looks like the middle value is missing, it isn"t
print([i for i in b"x00 x10"])
>>> [0, 32, 16]  # yep, all still there

Bearbeitet aufgrund eines besseren Verständnisses der Frage, nachdem es geklärt wurde.