Pythonのstructモジュールでバイナリデータを扱う方法【pack/unpack徹底解説】
Python標準ライブラリのstructモジュールは、C言語の構造体(struct)とPythonのbytesオブジェクトとの間でデータを相互変換するための強力な機能を提供します。バイナリファイルの読み書きやネットワークプロトコルの実装など、低レベルのデータ操作が必要な場面で活躍するモジュールです。
structモジュールでは、モジュールレベルの関数を使う方法と、Structクラスおよびそのメソッドを使う方法の2通りが用意されています。
フォーマット文字列によるバイトオーダーの指定
変換処理にはフォーマット文字列を使用します。フォーマット文字列の先頭に置く文字によって、バイトオーダー(エンディアン)、サイズ、アライメントが決定されます。
| 文字 | バイトオーダー | サイズ | アライメント |
|---|---|---|---|
| @ | ネイティブ | ネイティブ | ネイティブ |
| = | ネイティブ | 標準 | なし |
| < | リトルエンディアン | 標準 | なし |
| > | ビッグエンディアン | 標準 | なし |
| ! | ネットワーク(= ビッグエンディアン) | 標準 | なし |
C言語の型とフォーマット文字の対応表
次の表は、C言語の各型に対応するフォーマット文字と、それがPythonのどの型にマッピングされるかを示したものです。
| フォーマット | C言語の型 | Pythonの型 |
|---|---|---|
| x | パディングバイト | 値なし |
| c | char | 長さ1のbytes |
| b / B | signed char / unsigned char | 整数(int) |
| ? | _Bool | bool |
| h / H | short / unsigned short | 整数(int) |
| i / I | int / unsigned int | 整数(int) |
| l / L | long / unsigned long | 整数(int) |
| f | float | 浮動小数点数(float) |
| d | double | 浮動小数点数(float) |
| s | char[] | bytes |
| p | char[](Pascal文字列) | bytes |
| P | void * | 整数(int) |
structモジュールの主な関数
pack()関数
pack()は、指定されたフォーマット文字列に従って値をパックし、bytesオブジェクトとして返します。引数として渡す値は、フォーマット文字列が要求する型・個数と一致している必要があります。
unpack()関数
unpack()は、バッファからフォーマット文字列に従ってデータを展開します。戻り値は、要素が1つだけの場合でも必ずタプルとして返される点に注意してください。
実行例:pack()とunpack()の基本
import struct
student = (1, b'Rahul', 65.75)
packed = struct.pack('I 5s f', *student)
print('packed data:', packed)
unpacked = struct.unpack('I 5s f', packed)
print('unpacked data:', unpacked)出力結果
packed data: b'\x01\x00\x00\x00Rahul\x00\x00\x00\x00\x80\x83B' unpacked data: (1, b'Rahul', 65.75)
この例では、整数(unsigned int)、5バイトの文字列、floatの3つの値を1つのbytesオブジェクトにまとめ、その後元のタプルに復元しています。
Structクラスを使った効率的な変換
パック/アンパックはStructクラスのメソッドでも行えます。同じフォーマット文字列を繰り返し使う場合は、Structオブジェクトを一度生成してメソッドを呼び出す方が効率的です。これは、フォーマット文字列のコンパイルが一度だけで済むためです。
Struct(format)コンストラクタ
このコンストラクタは、指定されたフォーマット文字列に従ってバイナリデータの読み書きを行う新しいStructオブジェクトを返します。
pack()メソッド
コンパイル済みのフォーマットを使用する点以外は、struct.pack()関数と同一の動作をします。
unpack()メソッド
こちらも同様に、コンパイル済みのフォーマットを使用する点を除けば、struct.unpack()関数と同一です。
Structクラスの使用例
s = struct.Struct('I 5s f')
packed = s.pack(*student)
print(packed)
unpacked = s.unpack(packed)
print(unpacked)namedtupleとの組み合わせで可読性アップ
アンパックしたデータは、namedtuple(名前付きタプル)に直接変換すると、各フィールドに名前でアクセスできて便利です。
from collections import namedtuple
newstudent = namedtuple('newstudent', 'No Name Marks')
s1 = newstudent._make(struct.unpack('I 5s f', packed))
print(s1)出力結果
newstudent(No=1, Name=b'Rahul', Marks=65.75)
このようにstructモジュールを使いこなすことで、C言語との連携やバイナリ形式ファイルの解析など、Pythonでのバイナリデータ処理を効率的かつ安全に行えるようになります。
-
Pythonで身につける統計的思考 ― グラフとチャートによるデータ分析入門
統計学は、機械学習(ML)やAIを学ぶうえで欠かせない基礎知識です。これらの技術分野ではPythonが事実上の標準言語となっているため、統計分析を取り入れたPythonプログラムの書き方をマスターすることが重要になります。本記事では、さまざまなPythonライブラリを活用してグラフやチャートを作成する方法を解説します。多様なチャートを使いこなせるようになると、データを素早く分析し、結論を視覚的に導き出せるようになります。 データの準備 ここでは、さまざまな種子(シード)に関するデータを含むデータセットを使用します。このデータセットはKaggleから入手でき、URLは後述のサンプルコード内に記載
-
Pythonで国勢調査データを分析する方法|インドの人口統計データを可視化してみよう
国勢調査(センサス)とは、特定の対象人口に関する情報を体系的に記録・収集する取り組みです。収集されるデータには、人口統計、経済状況、居住環境など、さまざまなカテゴリの情報が含まれています。これらのデータは、政府が現状を正確に把握し、将来に向けた政策立案を行ううえで重要な基礎資料となります。本記事では、Pythonを活用してインドの国勢調査データを分析する方法を解説します。人口動態や経済指標など複数の観点からデータを掘り下げ、その結果をグラフとして視覚的に表現します。使用するデータセットはKaggleから入手した「India Districts Census 2011」です。データの準備と読み込