Qual è il modo corretto per convertire i byte in una stringa esadecimale in Python 3?


236

Qual è il modo corretto per convertire i byte in una stringa esadecimale in Python 3?

Vedo le affermazioni di un bytes.hexmetodo, i bytes.decodecodec e ho provato altre possibili funzioni di minimo stupore senza risultati. Voglio solo i miei byte esadecimali!


"senza risultati"? Quali problemi o errori specifici stai riscontrando? Si prega di mostrare il codice e gli errori.
S.Lott

Risposte:



95

Usa il binasciimodulo:

>>> import binascii
>>> binascii.hexlify('foo'.encode('utf8'))
b'666f6f'
>>> binascii.unhexlify(_).decode('utf8')
'foo'

Vedi questa risposta: Python 3.1.1 stringa in esadecimale


8
Questo è buono. Sconcertante è che puoi convertire hex in byte usando bytes.fromhex (hex_str), ma non puoi convertire byte in hex usando bytes.tohex () - qual è il razionale in questo?
nagylzs,

1
Immagino che la relazione tra byte ed hex non sia una proprietà di nessuno dei due (il che non risponde al motivo per cui fromhex è presente). Sembra che non sia stata solo una svista, ma qualcosa su cui si è discusso: bugs.python.org/issue3532#msg70950 . D: Sarebbe male avere anche il metodo tohex dell'oggetto byte per eseguire anche questa attività? A: IMO, sì, lo sarebbe. Ciò complica il codice e distoglie l'attenzione dal corretto approccio alla conversione dei dati (vale a dire funzioni, non metodi).
Mu Mind,

3
Questo risponde davvero alla domanda? Non restituisce un esagono strma a bytes. So che l'OP sembra contento della risposta ma non sarà meglio espandere questa risposta per includerla .decode("ascii")anche per convertirla in una "stringa"
RubenLaguna

3
Stavo pensando che molte persone rispondono a questa domanda / risposta alla ricerca di un modo per stampare a bytes. Se si print(b'666f6f')ottiene bla stampa. Se .decode("ascii")poi non lo fai. Basti pensare a come quelli che avevano effettivamente bytes( un vero binario con elementi> 128, non una stringa ASCII) volessero stamparlo.
RubenLaguna,

5
@nagylzs: esiste un .hex()metodo in Python 3.5+
jfs

43

Python ha codec standard byte per byte che eseguono comode trasformazioni come quoted-stampabile (si adatta in ascii a 7 bit), base64 (si adatta in alfanumerici), escape esadecimale, compressione gzip e bz2. In Python 2, puoi fare:

b'foo'.encode('hex')

In Python 3, str.encode/ bytes.decodesono strettamente per le conversioni di byte <-> str. Invece, puoi farlo, che funziona su Python 2 e Python 3 ( s / encode / decode / g per l'inverso):

import codecs
codecs.getencoder('hex')(b'foo')[0]

A partire da Python 3.4, c'è un'opzione meno imbarazzante:

codecs.encode(b'foo', 'hex')

Questi codec diversi sono accessibili anche all'interno dei propri moduli (base64, zlib, bz2, uu, quopri, binascii); l'API è meno coerente, ma per i codec di compressione offre un maggiore controllo.


1
usando python 3.3:LookupError: unknown encoding: hex
Janus Troelsen il

@JanusTroelsen: prova 'hex_codec' . O semplicemente usa binascii.hexlify(b'foo')direttamente
jfs

7
import codecs
codecs.getencoder('hex_codec')(b'foo')[0]

funziona in Python 3.3 (quindi "hex_codec" invece di "hex").


Forse interessante, in Python 3.4 "hex" o "hex_codec" funziona bene.
Stephen Paulger,

6

Il metodo binascii.hexlify()verrà convertito bytesin una bytesstringa esadecimale che rappresenta. Ciò significa che ogni byte nell'input verrà convertito in due caratteri ASCII. Se vuoi un vero strrisultato, puoi ottenere .decode("ascii")il risultato.

Ho incluso uno snippet che lo illustra.

import binascii

with open("addressbook.bin", "rb") as f: # or any binary file like '/bin/ls'
    in_bytes = f.read()
    print(in_bytes) # b'\n\x16\n\x04'
    hex_bytes = binascii.hexlify(in_bytes) 
    print(hex_bytes) # b'0a160a04' which is twice as long as in_bytes
    hex_str = hex_bytes.decode("ascii")
    print(hex_str) # 0a160a04

dalla stringa esadecimale "0a160a04"a può tornare al bytescon binascii.unhexlify("0a160a04")cui restituisceb'\n\x16\n\x04'


3

OK, la seguente risposta è leggermente al di là dell'ambito se ti interessa solo Python 3, ma questa domanda è il primo hit di Google anche se non specifichi la versione di Python, quindi ecco un modo che funziona sia su Python 2 che su Python 3 .

Sto anche interpretando la domanda sulla conversione di byte nel strtipo: vale a dire, byte-y su Python 2 e Unicode-y su Python 3.

Detto questo, l'approccio migliore che conosco è:

import six

bytes_to_hex_str = lambda b: ' '.join('%02x' % i for i in six.iterbytes(b))

La seguente affermazione sarà vera per Python 2 o Python 3, supponendo che tu non abbia attivato il unicode_literalsfuturo in Python 2:

assert bytes_to_hex_str(b'jkl') == '6a 6b 6c'

(Oppure puoi usare ''.join()per omettere lo spazio tra i byte, ecc.)


3

può essere utilizzato l'identificatore di %x02formato che formatta e genera un valore esadecimale. Per esempio:

>>> foo = b"tC\xfc}\x05i\x8d\x86\x05\xa5\xb4\xd3]Vd\x9cZ\x92~'6"
>>> res = ""
>>> for b in foo:
...     res += "%02x" % b
... 
>>> print(res)
7443fc7d05698d8605a5b4d35d56649c5a927e2736

Secondo me, è la risposta migliore perché funziona con tutte le versioni di Python e non ha bisogno di alcuna importazione. Tuttavia, vorrei visualizzare le stringhe hexa in maiuscolores.upper()
Bruno L.


0

Se vuoi convertire b '\ x61' in 97 o '0x61', puoi provare questo:

[python3.5]
>>>from struct import *
>>>temp=unpack('B',b'\x61')[0] ## convert bytes to unsigned int
97
>>>hex(temp) ##convert int to string which is hexadecimal expression
'0x61'

Riferimento: https://docs.python.org/3.5/library/struct.html


In qualche modo mi aiuta con esp32
Tejas Tank il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.