So konvertieren/dekodieren Sie Solidity bytes32 über web3.py in eine Python-Zeichenfolge

In einem Solidity-Vertrag habe ich diese Variable: zBytes32 = "HelloBytes32";

nachdem Python web3.py diese Variable abgerufen hat,

zbytes32 = contractInstance.functions.getzBytes32().call()

print(zbytes32) zeigt den Wert von zbytes32:

# b'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

zbytes32 = zBytes32.decode('utf8')# shows HelloBytes32
print(zbytes32) 

decode('utf8') entfernt b im Vordergrund, print() verbirgt ALLE \x00, aber sie sind NOCH DA!!! Es zu beweisen:

zBytes32str= str(zbytes32)
print('zbytes32 = '+ zBytes32str)
if zBytes32str == 'HelloBytes32':
    print('zbytes32str == "HelloBytes32"')
else:
    print('zbytes32str != "HelloBytes32"')

zbytes32str != "HelloBytes32" wird angezeigt!!! WIE KANN ich byte32 in Python richtig decodieren?

print('\ngetBytes32 raw: {}'.format(zbytes32))# shows HelloBytes32
print('zbytes32.decode("utf8") as string = '+ zbytes32)# shows HelloBytes32

OBWOHL sie genauso aussehen wie HelloBytes32, sind sie es eigentlich NICHT!

Vielleicht erklärt das folgende Situation:

arr = contractInstance.functions.getVariables().call()
print('arr[4] in str()= '+ str(arr[4]))#must be converted to string
b2= arr[4].decode('utf8')
print('b2.decode("utf8")= '+ b2)
arr[4] = ''
print('after arr[4] = "", arr[4]= '+ arr[4])
arr[4] = b2
print('after arr[4] = b2, arr[4]= '+ arr[4])
arr[0] = 'What man?'
print('after arr[0] = "What man?", arr[0]= '+ arr[0])
print('\nget many variables: {}'.format(arr))

es zeigt im terminal:

arr[4] in str()= b'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b2.decode("utf8")= HelloBytes32
after arr[4] = "", arr[4]= 
after arr[4] = b2, arr[4]= HelloBytes32
after arr[0] = "What man?", arr[0]= What man?

get many variables: ['What man?', '0x583031D11...', 111111, False, 'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ['0xCA35b7d...', '0x14723A...'], [9999999, 555555]]

Siehe das obige Array. Wenn ich einen neuen Wert auf arr[0] setze, funktioniert es.

Aber wenn ich einen neuen Wert für arr[4] setze, funktioniert es irgendwie ...

WARUM zeigt arr[4] immer noch diese \x00 an, wenn ich das gesamte Array zeige ???

Ich muss diese Werte an ein anderes Skript weitergeben, damit ich sicherstellen muss, dass sie sauber von diesen \x00 sind. Bitte helfen Sie. Danke

Antworten (3)

Das Problem hier ist, dass Ihre Variable eine feste Länge von 32 Bytes hat, was die Nullen rechts erklärt. Sie können die Nullen in Python entfernen:

zbytes32 = contractInstance.functions.getzBytes32().call()
zbytes32 = zbytes32.hex().rstrip("0")
if len(zbytes32) % 2 != 0:
    zbytes32 = zbytes32 + '0'
zbytes32 = bytes.fromhex(zbytes32).decode('utf8')

Das Drucken der Variablen zbytes32 ergibt: 'HelloBytes32' und: zbytes32=='HelloBytes32'isTrue

Der bedingte Teil if len(zbytes32) % 2 != 0ist da, weil es sein kann, dass das letzte Zeichen tatsächlich Null ist und wir es entfernen. Der Weg, dies zu wissen, ist, dass jedes Byte durch zwei hexadezimale Zeichen dargestellt wird, also wenn die Länge der Variablen zbytes32 nach dem Entfernen der Nullen ist ungerade muss rechts eine Null hinzugefügt werden.

Hoffe das hilft

DANKE Jaime! Ich habe auch diese Antwort gegeben: How to convert/encode string to bytes32 in Python for Solidity bytes32 arguments via web3.py ethereum.stackexchange.com/questions/30683/…

Da Sie anscheinend davon ausgehen, dass die Bytes mit UTF-8 dekodierbar sind, möchten Sie vielleicht tatsächlich einen stringTyp in Solidity anstelle von bytes32.

Wenn Sie den Variablentyp in String ändern und erneut bereitstellen, würde der web3.py-Vertrag mit der neuen ABI eine bereits decodierte Zeichenfolge als zurückgeben "HelloBytes32".

Danke Schnitzer. Das ist gut darauf hinzuweisen, dass ich davon ausgegangen bin, dass es mit UTF-8 dekodierbar ist. Das sollte mir bewusst sein. Danke
from web3 import Web3
string_content = Web3.toText(bytes_content)