Ich habe von Python 2 auf Python 3 aktualisiert und einige Codes, die früher funktionierten, sind jetzt kaputt. Ich kann es anscheinend nicht reparieren. Irgendwelche Vorschläge?
Arbeitete in Python 2
# Convert hex string to byte array
hex_string = "0x00012345...."
data_bytearray = bytearray.fromhex(hex_string.replace("0x", ""))
# Then I pass data_bytearray into transactions.Transaction and it works.
try:
return {'error': False, 'sign': rlp.encode(transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data_bytearray).sign(privkey)).encode('hex')}
except Exception as msg:
return {'error': True, 'message': msg}
Derselbe Code funktioniert nicht in Python 3 und beachten Sie, dass sich der Datentyp des Byte-Arrays in geändert hat
<class 'bytearray'> # python 3 produces this from bytearray.fromhex
<type 'bytearray'> # python 2 produces this from bytearray.fromhex
Ich bekomme folgenden Fehler:
{'error': True, 'message': ObjectSerializationError('Serialization failed because of field data ("Object is not a serializable (<class \'bytearray\'>)")',)}
Ich habe versucht, die Ausgabe mit Pickle zu serialisieren, habe aber einen anderen Fehler erhalten:
import pickle
data_bytearray = pickle.dumps(data_bytearray)
{'error': True, 'message': AttributeError("'bytes' object has no attribute 'encode'",)}
Was mache ich hier falsch?
Lösung:
try:
data_hex_with0xRemoved = data_hex.replace("0x", "")
# If I use bytearray.fromhex, it results in {'error': True, 'message': ObjectSerializationError('Serialization failed because of field data ("Object is not a serializable (<class \'bytearray\'>)")',)}
# data = bytearray.fromhex('deadbeef')
# So instead I use bytes.fromhex
data = bytes.fromhex(data_hex_with0xRemoved)
unsigned_transaction = transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data)
raw_transaction_bytes = rlp.encode(unsigned_transaction.sign(privkey))
raw_transaction_hex = Web3.toHex(raw_transaction_bytes)
raw_transaction_hex_0xRemoved = raw_transaction_hex.replace("0x", "")
return {'error': False, 'sign': raw_transaction_hex_0xRemoved}
except Exception as msg:
return {'error': True, 'message': msg}
try:
unsigned_transaction = transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data_bytearray)
raw_transaction = rlp.encode(unsigned_transaction.sign(privkey))
return {'error': False, 'sign': Web3.toHex(raw_transaction)}
except Exception as msg:
return {'error': True, 'message': msg}
Die einzige bemerkenswerte Änderung ist von raw_transaction.encode('hex')
zu Web3.toHex(raw_transaction)
.
Die anderen Unterschiede zur ursprünglichen Zeile bestanden lediglich darin, die Menge an Logik pro Zeile zu reduzieren.
Sowohl Bytes als auch Web3.toBytes gaben mir einen ähnlichen Fehler wie pickle.dumps:
{'error': True, 'message': AttributeError("'bytes' object has no attribute 'encode'",)}
Dieser ^-Kommentar war am hilfreichsten, obwohl er nicht erklärt, warum Sie nicht denselben Fehler mit bytearray
(ich denke, Sie sollten) erhalten. Sehen:
In [1]: b'\xaf'.encode('hex')
AttributeError: 'bytes' object has no attribute 'encode'
In [2]: bytearray(b'\xaf').encode('hex')
AttributeError: 'bytearray' object has no attribute 'encode'
Das hat nicht wirklich etwas mit Ethereum zu tun, sondern nur damit, zu lernen, wie das Codieren und Beizen in Python 3 funktioniert. Ich würde beispielsweise erwarten, dass sich Folgendes genau so verhält wie das erste Codebeispiel aus der Frage:
try:
return {'error': False, 'sign': bytearray(b'\xaf').encode('hex')}
except Exception as msg:
return {'error': True, 'message': msg}
Die Codierung in Python 2 hatte eine schlampige API und erlaubte es den Leuten, unsinnige Dinge zu tun, wie z. B. Binärdaten zu „codieren“ (die bereits codiert sind, also binär sind). Also, encode()
wurde ganz aus dem bytes
Typ Python 3 entfernt. Wenn Sie in Python 3 in Hex konvertieren möchten bytes
, gibt es einige Möglichkeiten, dies zu tun:
> Web3.toHex(b'\xaf')
'0xaf'
> b'\xaf'.hex()
'af'
# note that you don't get the "0x" prefix
> import binascii
> hex_in_bytes = binascii.hexlify(b'\xaf')
b'af'
# binascii made the nonsensical choice to return the hex value in a `bytes` type
# which you can fix up by decoding to a string
> hex_in_bytes.decode('utf8')
'af'
(Alle außer Web3
funktionieren bytearray
auch mit).
data = Web3.toBytes(hexstr=data_hex)
.
Schnitzer
bytes
stattdessen versuchtbytearray
? Außerdem könnte Ihnen gefallen:data_bytes = Web3.toBytes(hexstr="0x00012345")
from web3.pyHolly Rosenberg
Lampenschirm