Python 3 で16進数とバイト列の相互変換

More than 1 year has passed since last update.


概要

文字列のテストデータを動的に生成する場合、16進数とバイト列の相互変換が必要になります。整数とバイト列、16進数とバイト列の変換だけでなく表示方法にもさまざまな選択肢があります。文字列とバイト列の相互変換について調べた記事はこちらの記事に分割しました。


整数と16進数文字列の相互変換

ビルトインの format 関数や hex を使うことができます。Python 2 系との互換性を保つのであれば、% を使います。

>>> format(0xabcd, 'x')

'abcd'
>>> hex(0xabcd)
'0xabcd'
>>> '%02x' % 0xabcd
'abcd'

str.format も使うことができます。

>>> '{:02x}'.format(0xabcd)

'abcd'

16進数文字列を整数に変換するには int を使います。

>>> int('0xabcd', 16)

43981
>>> int('abcd', 16)
43981


16進数文字列とバイト列の相互変換


bytes.fromhex と bytes.hex

bytes.fromhexbytes.hex は組み込みのメソッドです。bytes.hex は Python 3.5 で追加されました。

>>> bytes.fromhex('abcd')

b'\xab\xcd'
>>> b'\xab\xcd'.hex()
'abcd'


binascii.unhexlify と binascii.hexlify

binascii モジュールをインポートする必要があります。

>>> import binascii

>>> binascii.unhexlify('abcd')
b'\xab\xcd'
>>> str(binascii.hexlify(b'\xab\xcd'), 'utf-8')
'abcd'

エイリアスも用意されています。

>>> binascii.a2b_hex('abcd')

b'\xab\xcd'
>>> str(binascii.b2a_hex(b'\xab\xcd'), 'utf-8')
'abcd'


codecs.decode と codecs.encode

binascii.a2b_hex()binascii.b2a_hex() と同じとマニュアルに明記されています。

>>> import codecs

>>> codecs.decode('abcd', 'hex')
b'\xab\xcd'
>>> codecs.encode(b'\xab\xcd', 'hex')
b'abcd'
>>> str(b'abcd', 'utf-8')
'abcd'

codecs.getdecodercodecs.getencoder はタプルを返します。

>>> codecs.getdecoder('hex')('abcd')

(b'\xab\xcd', 4)
>>> codecs.getencoder('hex')(b'\xab\xcd')
(b'abcd', 2)
>>> str(b'abcd', 'utf-8')
'abcd'


整数とバイト列の相互変換


int.to_bytes と int.from_bytes

Python 3.2 から利用できます。

>>> """ https://stackoverflow.com/a/30375198/531320 """

>>> x = 0xabcd
>>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='big')
b'\xab\xcd'
>>> format(int.from_bytes(b'\xab\xcd', byteorder='big'), 'x')
'abcd'


struct.pack と struct.unpack

struct.packstruct.unpack で使えるフォーマットの記号の意味はほかのプログラミング言語と異なります。

>>> struct.pack('BB', 0xab, 0xcd)

b'\xab\xcd'

リストをパックして渡すことができます。

>>> x = [0xab, 0xcd]

>>> struct.pack('B'* len(x), *x)
b'\xab\xcd'

struct.unpack はタプルを返します。

>>> x = b'\xab\xcd'

>>> struct.unpack('B' * len(x), x)
(171, 205)


16進数文字列経由

整数を16進数文字列に変換してから文字列に変換する方法もあります。メリットは整数の桁数を指定しなくてよいことです。

>>> bytes.fromhex(format(0xabcd, 'x'))

b'\xab\xcd'
>>> b'\xab\xcd'.hex()
'abcd'
>>> int(b'\xab\xcd'.hex(), 16)
43981
>>> 0xabcd
43981