ユーニックス総合研究所

  • home
  • archives
  • python-bytes

Pythonのbytes(バイト列)の使い方

  • 作成日: 2023-12-24
  • 更新日: 2023-12-24
  • カテゴリ: Python

Pythonのbytes(バイト列)とは?

Pythonで文字列などの連続したデータを扱う場合、大きく分けて以下の二つがあります。

  • str(文字列)
  • bytes(バイト列)

文字列というのは一般的によく使われる文字の集まりです。
PythonでHello, World!するときもこの文字列でprint()を呼び出しています。

バイト列(bytes)というのは、バイトの集まりのことです。バイトは8ビットで1バイトなのでこの1バイトが連続して並んでいるのがバイト列です。
これはたとえばソケットの通信データや画像のデータを扱う場合などに使われます。

この記事ではこのbytesについて解説していきます。

バイナリシーケンス型 --- bytes, bytearray, memoryview - Python 3.12.1 ドキュメント

関連記事:
Pythonで文字列抽出【インデックスとスライス】
Pythonではこんなに簡単に文字列を検索できます: in演算子, find, reの正規表現
Pythonのstr.find(), str.rfind()の使い方
Pythonで文字列を連結または結合する方法: +演算子、join, format, f文字列など
Pythonの文字列の使い方を簡単にまとめた
Pythonで文字列を置換する具体的な方法(replace, re.sub)
Pythonによる文字列の分割: 区切り文字列、正規表現、改行などによる分割方法を解説

バイト列を得る方法

Pythonでバイト列のデータを定義するのは簡単です。
これはシングルクォートやダブルクォートで囲まれている文字列の先頭にbというプリフィックスを付けます。

# バイト列の定義  
byte_data = b'abc123'  

# バイト列を出力  
print(byte_data)  # b'abc123'  

このbを付けたリテラルを「bytesリテラル」と言います。
バイト列は文字列と同様にインデックスでアクセスしたり、スライスを使って部分を切り取ることができます。

data = b'abc123'  

print(data[0])  # 97  
print(data[1])  # 98  

for b in data:  
    print(b)  
    # 97  
    # 98  
    # 99  
    # 49  
    # 50  
    # 51  

print(data[3:])  # b'123'  

上記のようにバイト列の要素はprint()などで出力すると、数値になっている点に注意してください。
ですのでif文などで要素を比較するときは数値で比較しないといけません。

data = b'abc123'  

if data[0] == 97:  
    print('0 is a')  
    # 0 is a  

もちろんバイト列ごとの比較は以下のようにbプリフィックスを付けたリテラルで行えます。

data = b'abc123'  

if data == b'abc123':  
    print('true')  
    # true  

bytesリテラルの色々

bytesリテラルは全部で三種類あります。
以下の3つです。

  • シングルクォートのbytesリテラル
  • ダブルクォートのbytesリテラル
  • 3重クォートのbytesリテラル
b'Hello, World!'  
b"Hello, World!"  
b'''Hello,  
World!'''  
b"""Hello,  
World!"""  

この辺は文字列と一緒です。

bytesクラスの使い方

bプリフィックスの他にはbytesクラスを使う方法もあります。
イニシャライザは

class bytes([source[, encoding[, errors]]])  

のように定義されています。
文字列をsourceにしてencodingにエンコーディングを指定すると、文字列がバイト列に変換されます。

print(bytes('123', 'utf-8'))  
# b'123'  

print(bytes('あいう', 'utf-8'))  
# b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86'  

print(bytes('あいう', 'cp932'))  
# b'\x82\xa0\x82\xa2\x82\xa4'  

上記では「あいう」のバイト列がエンコーディングutf-8cp932で変わっていることに注目してください。
このようにバイト列はエンコーディングによって表現されるバイトの並びが変わります。
これは、特定のエンコーディングのバイト列は、その特定のエンコーディングで文字列に変換できるということになります。

また、bytesに数値を直接指定すると、その数の0埋めされた要素数のバイト列を得られます。

print(bytes(10))  
# b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'  

range()を指定した場合は連番のバイト列を得ることができます。

print(bytes(range(10)))  
# b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'  

rプリフィックスによるエスケープシーケンスの無効化

bytesリテラルにはrプリフィックスを付けることができます。
これを付けるとリテラル内のエスケープシーケンスが無効化されます。

# 無効化していない場合  
print(b'123\nabc\tdef')  
# b'123\nabc\tdef'  

# 無効化している場合  
print(br'123\nabc\tdef')  
# b'123\\nabc\\tdef'  

fromhexメソッド

classmethod fromhex(string)  

bytesのメソッドですがこれを使うと16進数の文字列からバイト列を得ることができます。

# 16進数の文字列をバイト列に変換  
print(bytes.fromhex('0048 0065 006c 006c 006f'))  
# b'\x00H\x00e\x00l\x00l\x00o'  

# 文字列にしてみると・・・  
print(bytes.fromhex('0048 0065 006c 006c 006f').decode())  
# Hello  

fromhex()に渡す文字列の16進数は2桁(0048など)で指定する必要があります。

hexメソッド

hex([sep[, bytes_per_sep]])  

Pythonのバージョン3.5から使えるメソッドです。
バイト列の16進数を文字列にします。

print(b'\xf0\xf1\xf2'.hex())  
# f0f1f2  

print(bytes.fromhex('0048 0065 006c 006c 006f').hex())  
# 00480065006c006c006f  

文字列からバイト列に変換する

文字列からバイト列に変換するにはencode()を使います。

str.encode() — Python 3.12.1 ドキュメント

これはstrのメソッドとして定義されています。

str.encode(encoding='utf-8', errors='strict')  
print('123'.encode())  # b'123'  

デフォルトのエンコーディングはUTF-8です。
エンコーディングを変えたい場合はencode()の引数に指定します。

'123'.encode('cp932')  
'123'.encode(encoding='cp932')  

errorsの文字列の意味は以下になります。

  • 'strict' ... エラー時にUnicodeError例外が送出される
  • 'ignore' ... エラー時に無視する
  • 'replace' ... エラー時にエラー文字を'?'に置換する
  • 'backslashreplace' ... エラー時にエラー文字をバックスラッシュでエスケープされたシーケンスで置換する

バイト列から文字列に変換する

バイト列を文字列に変換したい場合はdecode()を使います。

bytes.decode() ― Python 3.12.1 ドキュメント

「アル『バイト』のお『でこ』に文字列が光る」で覚えておきましょう。

bytes.decode(encoding='utf-8', errors='strict')  
print(b'123'.decode())  # '123'  

bytes.decode()str.encode()と同様にエンコーディングを変更したい場合は引数に指定します。

b'123'.decode('cp932')  
b'123'.decode(encoding='cp932')  

errorsに指定できる文字列は以下になります。

  • 'strict' ... エラー時にUnicodeError例外が送出される
  • 'ignore' ... エラー時に無視する
  • 'replace' ... エラー時にエラー文字を'?'に置換する

intをbytesに変換する

intをbytesに変換するにはint.to_bytes()が使えます。

a = 256  

print(a.to_bytes(2, 'big'))  # バイト数は2バイト。ビッグエンディアン  
# b'\x01\x00'  

print(a.to_bytes(4, 'little'))  # バイト数は4バイト。リトルエンディアン  
# b'\x00\x01\x00\x00'  
int.to_bytes(length=1, byteorder='big', *, signed=False)  

int.to_bytes() — Python 3.12.1 ドキュメント

第1引数のlengthにバイト数を指定し、第2引数のbyteorderにエンディアンを指定します。
bigがビッグエンディアンで最上位のバイトがバイト列の最初に来ます。
littleがリトルエンディアンで最上位のバイトがバイト列の最後に来ます。

bytesを結合する

関連記事
Pythonでバイナリファイルを分割・結合する

bytesの結合は演算子で行います。
bytes同士の結合は+演算で行えます。

data = b'123' + b'abc'  

print(data)  
# b'123abc'  

data = data + data  

print(data)  
# b'123abc123abc'  

bytesの変数のお尻にbytesを追加で結合したい場合は+=演算が使えます。

data = b'123'  
data += b'abc'  

print(data)      
# b'123abc'