Pythonでバイト列(bytes)と文字列(string)を相互に変換するには、encode
メソッドとdecode
メソッドを使用します。本記事では、これらの変換方法と注意点を実用的なコード例とともに解説します。
バイト列と文字列の基本
バイト列(bytes)とは
バイト列はコンピュータが直接扱うバイナリデータを表現するデータ型です。0から255までの整数値の配列として表現され、ファイル操作やネットワーク通信などで使用されます。
バイト列オブジェクトの作成方法を示します。
# バイト列オブジェクトの作成方法
b1 = b'Hello' # 文字列リテラルの前にbをつける
b2 = bytes([72, 101, 108, 108, 111]) # ASCII値のリストから作成
b3 = bytes.fromhex('48 65 6c 6c 6f') # 16進数文字列から作成
print(b1) # b'Hello'
print(b2) # b'Hello'
print(b3) # b'Hello'
print(type(b1)) # <class 'bytes'>
文字列(string)とは
文字列は人間が読み書きできるテキストデータを表現するデータ型です。Pythonの文字列はUnicodeをサポートしており、世界中のさまざまな言語の文字を扱えます。
文字列オブジェクトの作成方法を示します。
# 文字列オブジェクトの作成方法
s1 = 'Hello' # シングルクォート
s2 = "Hello" # ダブルクォート
s3 = """Hello
World""" # 三重引用符(複数行)
print(s1) # Hello
print(s2) # Hello
print(s3) # Hello
# World
print(type(s1)) # <class 'str'>
バイト列と文字列の変換方法
バイト列から文字列への変換(decode)
バイト列から文字列への変換には、decodeメソッドを使用します。変換時にはエンコーディング(文字コード)を指定する必要があります。
英語のテキストをデコードする例を示します。
# バイト列から文字列への変換
b = b'Hello, World!'
s1 = b.decode('utf-8') # UTF-8でデコード
s2 = b.decode('ascii') # ASCIIでデコード
print(b) # b'Hello, World!'
print(s1) # Hello, World!
print(type(s1)) # <class 'str'>
日本語などの非ASCII文字を含むバイト列をデコードする例を示します。
# 日本語を含むバイト列のデコード
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) # b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
print(s_japanese) # こんにちは
文字列からバイト列への変換(encode)
文字列からバイト列への変換には、encodeメソッドを使用します。変換時にはエンコーディングを指定する必要があります。
英語のテキストをエンコードする例を示します。
# 文字列からバイト列への変換
s = 'Hello, World!'
b1 = s.encode('utf-8') # UTF-8でエンコード
b2 = s.encode('ascii') # ASCIIでエンコード
print(s) # Hello, World!
print(b1) # b'Hello, World!'
print(type(b1)) # <class 'bytes'>
日本語などの非ASCII文字を含む文字列をエンコードする例を示します。
# 日本語を含む文字列のエンコード
s_japanese = 'こんにちは'
b_japanese = s_japanese.encode('utf-8') # UTF-8でエンコード
print(s_japanese) # こんにちは
print(b_japanese) # b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
print(b_japanese.hex()) # e38193e38293e381abe381a1e381af
変換時の注意点
エンコーディングの選択
文字列の変換では適切なエンコーディングの選択が重要です。一般的にはUTF-8が多言語対応に適しています。
異なるエンコーディングでの変換例を示します。
# 異なるエンコーディングの比較
s = '日本語'
b_utf8 = s.encode('utf-8')
b_sjis = s.encode('shift_jis') # 日本語向けエンコーディング
print(b_utf8) # b'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e'
print(b_sjis) # b'\x93\xfa\x96\x7b\x8c\xea'
print(len(b_utf8)) # 9
print(len(b_sjis)) # 6
エラー処理
変換時にエラーが発生した場合の処理方法を指定できます。errorsパラメータを使用して、エラー発生時の挙動を制御します。主な設定値は以下の通りです:
- strict:デフォルト値。エラーが発生すると例外(UnicodeEncodeError/UnicodeDecodeError)を発生させます
- ignore:エラーとなる文字を無視します。変換結果からその文字が削除されます
- replace:エラーとなる文字を置換文字に置き換えます
- エンコード時は「?」に置換
- デコード時は「�」(U+FFFD、REPLACEMENT CHARACTER)に置換
- backslashreplace:エラーとなる文字をバックスラッシュエスケープシーケンス(例:\xff)に置き換えます
適切なエラー処理方法を選択することで、変換エラーが発生しても処理を継続できます。
エンコード時のエラー処理例を示します。
# エンコード時のエラー処理
s = 'こんにちは'
try:
# ASCIIは日本語を扱えないのでエラーになる
b = s.encode('ascii')
except UnicodeEncodeError as e:
print(f"エラー: {e}") # エラー: 'ascii' codec can't encode character '\u3053' in position 0: ordinal not in range(128)
# エラー処理方法を指定
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) # b''
print(b_replace) # b'?????'
print(b_xmlcharrefreplace) # b'こんにちは'
デコード時のエラー処理例を示します。
# デコード時のエラー処理
# 無効なUTF-8バイト列
invalid_bytes = b'\xff\xfe\xfd'
try:
# 無効なバイト列をUTF-8としてデコードするとエラーになる
s = invalid_bytes.decode('utf-8')
except UnicodeDecodeError as e:
print(f"デコードエラー: {e}") # デコードエラー: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
# エラー処理方法を指定
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)) # '\\xff\\xfe\\xfd'
実用的な使用例
ファイル操作での変換
テキストファイルの読み書き時にエンコード・デコードが使われる例を示します。
# テキストファイルの読み書き
# ファイルへの書き込み
text = "こんにちは、世界!"
with open("sample.txt", "w", encoding="utf-8") as f:
f.write(text)
# ファイルからの読み込み
with open("sample.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content) # こんにちは、世界!
# バイナリモードでの読み込み
with open("sample.txt", "rb") as f:
binary_data = f.read()
print(binary_data) # b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf\xe3\x80\x81\xe4\xb8\x96\xe7\x95\x8c\xef\xbc\x81'
# バイナリデータを文字列に戻す
text_from_binary = binary_data.decode("utf-8")
print(text_from_binary) # こんにちは、世界!
ネットワーク通信での変換
HTTPリクエストでのデータ送受信時にエンコード・デコードが使われる例を示します。
import urllib.request
import json
# JSONデータの送信例
data = {"name": "山田太郎", "age": 30}
json_data = json.dumps(data) # 辞書をJSON文字列に変換
encoded_data = json_data.encode("utf-8") # バイト列に変換
# リクエストの作成(実際には送信しない例)
req = urllib.request.Request(
"https://example.com/api",
data=encoded_data,
headers={"Content-Type": "application/json"}
)
print(f"送信データ(文字列): {json_data}") # 送信データ(文字列): {"name": "山田太郎", "age": 30}
print(f"送信データ(バイト列): {encoded_data}") # 送信データ(バイト列): b'{"name": "\xe5\xb1\xb1\xe7\x94\xb0\xe5\xa4\xaa\xe9\x83\x8e", "age": 30}'
# レスポンスの受信と処理(模擬例)
response_bytes = b'{"status": "success", "message": "\xe5\x87\xba\xe5\x8a\x9b\xe6\x88\x90\xe5\x8a\x9f"}'
response_str = response_bytes.decode("utf-8") # バイト列を文字列に変換
response_data = json.loads(response_str) # JSON文字列を辞書に変換
print(f"受信データ(バイト列): {response_bytes}") # 受信データ(バイト列): b'{"status": "success", "message": "\xe5\x87\xba\xe5\x8a\x9b\xe6\x88\x90\xe5\x8a\x9f"}'
print(f"受信データ(文字列): {response_str}") # 受信データ(文字列): {"status": "success", "message": "出力成功"}
print(f"ステータス: {response_data['status']}") # ステータス: success
print(f"メッセージ: {response_data['message']}") # メッセージ: 出力成功
まとめ
Pythonでのバイト列と文字列の変換方法について解説しました。
- バイト列から文字列への変換には
decode()
メソッドを使用する - 文字列からバイト列への変換には
encode()
メソッドを使用する - 変換時には適切なエンコーディングを指定する(一般的にはUTF-8が推奨)
- エラー処理方法を指定することで、変換エラーに対処できる
これらの知識は、ファイル操作、ネットワーク通信、データ処理など、さまざまな場面で役立ちます。適切なエンコーディングを選択し、エラー処理を行うことで、安全なプログラムを作成することができます。