Pythonでバイナリデータを扱う際、前回の記事で紹介した「struct.pack」でデータをバイト列に変換したあと、必ず必要になるのがデータの復元(デコード)です。
この記事では、バイト列をPythonの数値や文字列に戻す「struct.unpack」と、メモリ効率の良い「struct.unpack_from」の使い方を、初心者にもわかりやすく解説します。
1. struct.unpackとは?(packの逆操作)
struct.unpackは、C言語の構造体のようなバイナリデータ(バイト列)を、Pythonのタプルに変換するための関数です。
前回の記事(struct.packの使い方)で作成したバイナリデータを、元の数値や文字列に戻す際に使用します。
基本的な書き方
import struct
# 例:int(4バイト)とfloat(4バイト)のバイナリデータ
binary_data = b'\x01\x00\x00\x00\x00\x00\x80\x3f'
# unpack(フォーマット, データ)
result = struct.unpack('<if', binary_data)
print(result)
# 出力: (1, 1.0)ポイント:
- 戻り値は常に「タプル」になります。要素が1つだけでも
(値,)という形で返ってきます。 - 第1引数のフォーマット文字列は、
packした時と全く同じにする必要があります。
2. エンディアンとフォーマット文字の復習
unpackを正しく行うためには、データの並び順(エンディアン)を指定することが重要です。
| 文字 | 意味 |
< | リトルエンディアン(Windowsなど一般的に使用) |
> | ビッグエンディアン(ネットワーク通信など) |
i | 4バイト整数 (int) |
f | 4バイト浮動小数点 (float) |
s | 文字列 (char[]) |
※詳細はstruct.packの記事を参照してください。
3. 大容量データに最適!struct.unpack_fromの使い方
通常のunpackは、データ全体のサイズとフォーマットのサイズが一致していないとエラー(struct.error)になります。
しかし、「長いバイナリデータの中の、特定の場所(オフセット)からデータを抜き出したい」という場面も多いはず。そんな時に便利なのが struct.unpack_from です。
unpack_fromのメリット
- スライス(
data[4:8]など)を使わずに済むため、余計なメモリコピーが発生せず高速。 - 「○バイト目から読み込む」という指定が簡単。
使用例:特定のオフセットから読み込む
import struct
# 12バイトのバイナリデータ(4バイトずつ int, int, int)
data = struct.pack('<iii', 10, 20, 30)
# 4バイト目(2番目のデータ)から1つ(int)だけ読み込みたい場合
# unpack_from(フォーマット, データ, オフセット)
result = struct.unpack_from('<i', data, 4)
print(result)
# 出力: (20,)4. よくあるエラーと対処法
error: unpack requires a buffer of 4 bytes
このエラーは、「フォーマットで指定したサイズ」と「実際のバイナリデータのサイズ」が合っていない時に発生します。
- 原因1:
unpackを使っているのに、データの一部だけを渡していない。 - 解決策: データの一部を抜き出したいなら
unpack_fromを使うか、スライスでサイズを合わせてください。
期待した数値にならない
- 原因: エンディアン(
<や>)の指定が間違っている可能性があります。 - 解決策: 書き込み側(pack)と読み込み側(unpack)でエンディアンの設定を統一しましょう。
5. まとめ
struct.unpack:バイナリデータをPythonの型に変換する(戻り値はタプル)。struct.unpack_from:データの途中の位置から効率よく読み込む。- 注意点:必ず
pack時と同じフォーマット文字列・エンディアンを使用する。
バイナリデータの扱いに慣れると、独自のファイルフォーマットの解析や、ハードウェアとの通信プログラムが書けるようになります。
まずはstruct.packでデータを作り、それをunpackで戻す練習から始めてみてください!

コメント