本記事では、Pythonでバイト列(bytes)と文字列(string)を変換する方法を解説します。データ処理やファイル操作、ネットワーク通信などで頻繁に必要となる変換処理について、具体的なコード例とともに説明します。
bytesとstring
まずは、bytesとstringがそれぞれ何かを簡単に説明します。
bytes
bytesはPythonにおけるバイナリデータを表現するためのデータ型です。コンピュータが直接扱うことができる形式で、0から255までの整数値の配列として表現されます。ファイルの読み書き、ネットワーク通信、暗号化処理など、バイナリデータを扱う場面で使用されます。
bytesオブジェクトは不変(イミュータブル)であり、一度作成すると内容を変更することはできません。変更可能なバージョンとしてbytearrayがあります。
bytesリテラルはbで始まる文字列として表現されます。
以下はbytesオブジェクトを作成する例です。
# bytesオブジェクトの作成
b1 = b'Hello' # 文字列リテラルの前にbをつける
b2 = bytes([72, 101, 108, 108, 111]) # ASCII値のリストから作成
b3 = bytes.fromhex('48 65 6c 6c 6f') # 16進数文字列から作成
print(b1)
print(b2)
print(b3)
print(type(b1))
# 出力:
# b'Hello'
# b'Hello'
# b'Hello'
# <class 'bytes'>
string
stringはPythonにおけるテキストデータを表現するためのデータ型です。人間が読み書きできる文字の配列として表現されます。Pythonの文字列はUnicodeをサポートしており、世界中のさまざまな言語の文字を扱うことができます。
stringオブジェクトも不変(イミュータブル)であり、一度作成すると内容を変更することはできません。
以下はstringオブジェクトを作成する例です。
# stringオブジェクトの作成
s1 = 'Hello' # シングルクォート
s2 = "Hello" # ダブルクォート
s3 = """Hello
World""" # 三重引用符(複数行)
print(s1)
print(s2)
print(s3)
print(type(s1))
# 出力:
# Hello
# Hello
# Hello
# World
# <class 'str'>
変換する方法
bytesとstringは異なるデータ型であるため、相互に変換する必要があります。以下では、それぞれの変換方法を説明します。
bytes → string
bytesからstringへの変換は、decodeメソッドを使用します。decodeメソッドは、バイト列をどのエンコーディング(文字コードを定義する規則、例:UTF-8、ASCII、Shift-JISなど)で解釈するかを指定する必要があります。
以下はbytesからstringへの変換例です。
# bytesからstringへの変換
b = b'Hello, World!'
s1 = b.decode('utf-8') # UTF-8でデコード
s2 = b.decode('ascii') # ASCIIでデコード
print(b)
print(s1)
print(type(s1))
# 出力:
# b'Hello, World!'
# Hello, World!
# <class 'str'>
日本語などの非ASCII文字を含むバイト列をデコードする例です。
# 日本語を含むbytesのデコード
b_japanese = b'\\xe3\\x81\\x93\\xe3\\x82\\x93\\xe3\\x81\\xab\\xe3\\x81\\xa1\\xe3\\x81\\xaf' # 「こんにちは」のUTF-8バイト列
s_japanese = b_japanese.decode('utf-8')
print(b_japanese)
print(s_japanese)
# 出力:
# b'\\xe3\\x81\\x93\\xe3\\x82\\x93\\xe3\\x81\\xab\\xe3\\x81\\xa1\\xe3\\x81\\xaf'
# こんにちは
string → bytes
stringからbytesへの変換は、encodeメソッドを使用します。encodeメソッドは、文字列をどのエンコーディングでバイト列に変換するかを指定する必要があります。
以下はstringからbytesへの変換例です。
# stringからbytesへの変換
s = 'Hello, World!'
b1 = s.encode('utf-8') # UTF-8でエンコード
b2 = s.encode('ascii') # ASCIIでエンコード
print(s)
print(b1)
print(type(b1))
# 出力:
# Hello, World!
# b'Hello, World!'
# <class 'bytes'>
日本語などの非ASCII文字を含む文字列をエンコードする例です。
# 日本語を含むstringのエンコード
s_japanese = 'こんにちは'
b_japanese = s_japanese.encode('utf-8') # UTF-8でエンコード
print(s_japanese)
print(b_japanese)
print(b_japanese.hex()) # 16進数表示
# 出力:
# こんにちは
# b'\\xe3\\x81\\x93\\xe3\\x82\\x93\\xe3\\x81\\xab\\xe3\\x81\\xa1\\xe3\\x81\\xaf'
# e38193e38293e381abe381a1e381af
注意点
bytesとstringの変換を行う際には、いくつかの注意点があります。
エンコーディングの選択
文字列をエンコード/デコードする際には、適切なエンコーディングを選択することが重要です。一般的には、UTF-8が最も広く使われており、多言語対応に適しています。
# 異なるエンコーディングの例
s = '日本語'
b_utf8 = s.encode('utf-8')
b_sjis = s.encode('shift_jis') # 日本語向けエンコーディング
print(b_utf8)
print(b_sjis)
print(len(b_utf8)) # バイト数
print(len(b_sjis)) # バイト数
# 出力:
# b'\\xe6\\x97\\xa5\\xe6\\x9c\\xac\\xe8\\xaa\\x9e'
# b'\\x93\\xfa\\x96\\x7b\\x8c\\xea'
# 9
# 6
エラー処理
エンコード/デコード時にエラーが発生した場合の処理方法を指定できます。errorsパラメータを使用して、エラー発生時の挙動を制御します。主な設定値は以下の通りです:
- ‘strict’:デフォルト値。エラーが発生すると例外を発生させる
- ‘ignore’:エラーとなる文字を無視する
- ‘replace’:エラーとなる文字を置換文字(?や�など)に置き換える
- ‘xmlcharrefreplace’:エラーとなる文字をXMLエンティティに置き換える(encodeのみ)
- ‘backslashreplace’:エラーとなる文字をバックスラッシュエスケープシーケンスに置き換える
以下はencodeでのエラー処理の例です。
# encodeのエラー処理の例
s = 'こんにちは'
try:
# ASCIIは日本語を扱えないのでエラーになる
b = s.encode('ascii')
except UnicodeEncodeError as e:
print(f"エラー: {e}")
# エラー処理方法を指定
b_ignore = s.encode('ascii', errors='ignore') # エラーを無視
b_replace = s.encode('ascii', errors='replace') # ?に置換
b_xmlcharrefreplace = s.encode('ascii', errors='xmlcharrefreplace') # XMLエンティティに置換
print(b_ignore)
print(b_replace)
print(b_xmlcharrefreplace)
# 出力:
# エラー: 'ascii' codec can't encode character '\\u3053' in position 0: ordinal not in range(128)
# b''
# b'?????'
# b'こんにちは'
以下はdecodeでのエラー処理の例です。
# decodeのエラー処理の例
# 無効なUTF-8バイト列
invalid_bytes = b'\\xff\\xfe\\xfd'
try:
# 無効なバイト列をUTF-8としてデコードするとエラーになる
s = invalid_bytes.decode('utf-8')
except UnicodeDecodeError as e:
print(f"デコードエラー: {e}")
# エラー処理方法を指定
s_ignore = invalid_bytes.decode('utf-8', errors='ignore') # エラーを無視
s_replace = invalid_bytes.decode('utf-8', errors='replace') # �に置換
s_backslash = invalid_bytes.decode('utf-8', errors='backslashreplace') # バックスラッシュエスケープに置換
print(repr(s_ignore))
print(repr(s_replace))
print(repr(s_backslash))
# 出力:
# デコードエラー: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
# ''
# '���'
# '\\\\xff\\\\xfe\\\\xfd'
まとめ
Pythonにおけるbytesとstringの変換方法について解説しました。
- bytesはバイナリデータを表現するためのデータ型で、b’…’のように表記される
- stringはテキストデータを表現するためのデータ型で、’…’のように表記される
- bytesからstringへの変換には、decode()メソッドを使用する
- stringからbytesへの変換には、encode()メソッドを使用する
- エンコーディングの選択が重要で、一般的にはUTF-8が推奨される
- エラー処理方法を指定することで、変換エラーに対処できる
これらの知識は、ファイル操作、ネットワーク通信、データ処理など、さまざまな場面で役立ちます。適切なエンコーディングを選択し、エラー処理を行うことで、安全で効率的なプログラムを作成することができます。