struct --- バイト列をパックされたバイナリデータとして解釈する

ソースコード: Lib/struct.py


This module converts between Python values and C structs represented as Python bytes objects. Compact format strings describe the intended conversions to/from Python values. The module's functions and objects can be used for two largely distinct applications, data exchange with external sources (files or network connections), or data transfer between the Python application and the C layer.

注釈

When no prefix character is given, native mode is the default. It packs or unpacks data based on the platform and compiler on which the Python interpreter was built. The result of packing a given C struct includes pad bytes which maintain proper alignment for the C types involved; similarly, alignment is taken into account when unpacking. In contrast, when communicating data between external sources, the programmer is responsible for defining byte ordering and padding between elements. See バイトオーダ、サイズ、アラインメント for details.

いくつかの struct の関数 (および Struct のメソッド) は buffer 引数を取ります。 これは バッファプロトコル (buffer Protocol) を実装していて読み取り可能または読み書き可能なバッファを提供するオブジェクトのことです。この目的のために使われる最も一般的な型は bytesbytearray ですが、バイトの配列とみなすことができるような他の多くの型がバッファプロトコルを実装しています。そのため、それらは bytes オブジェクトから追加のコピーなしで読み出しや書き込みができます。

関数と例外

このモジュールは以下の例外と関数を定義しています:

exception struct.error

様々な状況で送出される例外です。引数は何が問題なのかを記述する文字列です。

struct.pack(format, v1, v2, ...)

フォーマット文字列 format に従い値 v1, v2, ... をパックして、バイト列オブジェクトを返します。引数は指定したフォーマットが要求する型と正確に一致していなければなりません。

struct.pack_into(format, buffer, offset, v1, v2, ...)

フォーマット文字列 format に従い値 v1, v2, ... をパックしてバイト列にし、書き込み可能な buffer のオフセット offset 位置より書き込みます。オフセットは省略出来ません。

struct.unpack(format, buffer)

(pack(format, ...) でパックされたであろう) バッファ buffer を、書式文字列 format に従ってアンパックします。 値が一つしかない場合を含め、結果はタプルで返されます。 バッファのバイトサイズは、 calcsize() の返り値である書式文字列が要求するサイズと一致しなければなりません。

struct.unpack_from(format, /, buffer, offset=0)

バッファ buffer を、 offset の位置から書式文字列 format に従ってアンパックします。 値が一つしかない場合を含め、結果はタプルで返されます。 offset を始点とするバッファのバイトサイズは、少なくとも calcsize() の返り値である書式文字列が要求するサイズでなければなりません。

struct.iter_unpack(format, buffer)

バッファ buffer を、書式文字列 format に従ってイテレータ形式でアンパックします。 この関数が返すイテレータは、すべての内容を読み終わるまでバッファから一定の大きさのチャンクを読み取ります。 バッファのバイトサイズは、 calcsize() の返り値である書式文字列が要求するサイズの倍数でなければなりません。

イテレーション毎に書式文字列で指定されたタプルを yield します。

バージョン 3.4 で追加.

struct.calcsize(format)

書式文字列 format に従って、構造体 (それと pack(format, ...) によって作成されるバイト列オブジェクト) のサイズを返します。

書式文字列

Format strings describe the data layout when packing and unpacking data. They are built up from format characters, which specify the type of data being packed/unpacked. In addition, special characters control the byte order, size and alignment. Each format string consists of an optional prefix character which describes the overall properties of the data and one or more format characters which describe the actual data values and padding.

バイトオーダ、サイズ、アラインメント

By default, C types are represented in the machine's native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler). This behavior is chosen so that the bytes of a packed struct correspond exactly to the memory layout of the corresponding C struct. Whether to use native byte ordering and padding or standard formats depends on the application.

これに代わって、フォーマット文字列の最初の文字を使って、バイトオーダやサイズ、アラインメントを指定することができます。指定できる文字を以下のテーブルに示します:

文字

バイトオーダ

サイズ

アラインメント

@

native

native

native

=

native

standard

none

<

リトルエンディアン

standard

none

>

ビッグエンディアン

standard

none

!

ネットワーク (= ビッグエンディアン)

standard

none

フォーマット文字列の最初の文字が上のいずれかでない場合、'@' であるとみなされます。

ネイティブのバイトオーダはビッグエンディアンかリトルエンディアンで、ホストシステムに依存します。例えば、Intel x86、AMD64 (x86-64) および Apple M1 はリトルエンディアンです。IBM z および多くの古いアーキテクチャはビッグエンディアンです。使っているシステムでのエンディアンは sys.byteorder を使って調べて下さい。

ネイティブのサイズおよびアラインメントは C コンパイラの sizeof 式で決定されます。ネイティブのサイズおよびアラインメントはネイティブのバイトオーダと同時に使われます。

標準のサイズはフォーマット文字だけで決まります。 書式指定文字 の表を参照して下さい。

'@''=' の違いに注意してください: 両方ともネイティブのバイトオーダですが、後者のバイトサイズとアラインメントは標準のものに合わせてあります。

The form '!' represents the network byte order which is always big-endian as defined in IETF RFC 1700.

バイトオーダに関して、「(強制的にバイトスワップを行う)ネイティブの逆」を指定する方法はありません。'<' または '>' のうちふさわしい方を選んでください。

注釈:

  1. パディングは構造体のメンバの並びの中にだけ自動で追加されます。最初や最後にパディングが追加されることはありません。

  2. ネイティブでないサイズおよびアラインメントが使われる場合にはパディングは行われません (たとえば '<', '>', '=', '!' を使った場合です)。

  3. 特定の型によるアラインメント要求に従うように構造体の末端をそろえるには、繰り返し回数をゼロにした特定の型でフォーマットを終端します。 使用例 を参照して下さい。

書式指定文字

フォーマット文字 (format character) は以下の意味を持っています; C と Python の間の変換では、値は正確に以下に指定された型でなくてはなりません: 「標準のサイズ」列は standard サイズ使用時にパックされた値が何バイトかを示します。つまり、フォーマット文字列が '<', '>', '!', '=' のいずれかで始まっている場合のものです。native サイズ使用時にはパックされた値の大きさはプラットフォーム依存です。

フォーマット

C の型

Python の型

標準のサイズ

注釈

x

パディングバイト

値なし

(7)

c

char

長さ 1 のバイト列

1

b

signed char

整数

1

(1), (2)

B

unsigned char

整数

1

(2)

?

_Bool

真偽値型(bool)

1

(1)

h

short

整数

2

(2)

H

unsigned short

整数

2

(2)

i

int

整数

4

(2)

I

unsigned int

整数

4

(2)

l

long

整数

4

(2)

L

unsigned long

整数

4

(2)

q

long long

整数

8

(2)

Q

unsigned long long

整数

8

(2)

n

ssize_t

整数

(3)

N

size_t

整数

(3)

e

(6)

浮動小数点数

2

(4)

f

float

浮動小数点数

4

(4)

d

double

浮動小数点数

8

(4)

s

char[]

bytes

(9)

p

char[]

bytes

(8)

P

void*

整数

(5)

バージョン 3.3 で変更: 'n' および 'N' フォーマットのサポートが追加されました。

バージョン 3.6 で変更: 'e' フォーマットのサポートが追加されました。

注釈:

  1. '?' 変換コードは C99 で定義された _Bool 型に対応します。その型が利用できない場合は、 char で代用されます。標準モードでは常に1バイトで表現されます。

  2. 非整数を整数の変換コードを使ってパックしようとすると、非整数が __index__() メソッドを持っていた場合は、整数に変換するためにパックする前にそのメソッドが呼ばれます。

    バージョン 3.2 で変更: Added use of the __index__() method for non-integers.

  3. 'n' および 'N' 変換コードは (デフォルトもしくはバイトオーダ文字 '@' 付きで選択される) native サイズ使用時のみ利用できます。standard サイズ使用時には、自身のアプリケーションに適する他の整数フォーマットを使うことができます。

  4. 'f''d' および 'e' 変換コードについて、パックされた表現は IEEE 754 binary32 ('f' の場合) 、 binary64 ('d' の場合) 、またはbinary16('e' の場合) フォーマットが、プラットフォームにおける浮動小数点数のフォーマットに関係なく使われます。

  5. 'P' フォーマット文字はネイティブバイトオーダでのみ利用可能です (デフォルトのネットワークバイトオーダに設定するか、'@' バイトオーダ指定文字を指定しなければなりません)。'=' を指定した場合、ホスト計算機のバイトオーダに基づいてリトルエンディアンとビッグエンディアンのどちらを使うかを決めます。struct モジュールはこの設定をネイティブのオーダ設定として解釈しないので、'P' を使うことはできません。

  6. IEEE 754 の binary16 "半精度" 型は、 IEEE 754 standard の2008 年の改訂で導入されました。 半精度型は、符号 bit 、5 bit の指数部、 11 bit の精度 (明示的には 10 bit が保存される) を持ち、おおよそ 6.1e-05 から 6.5e+04 までの数を完全な精度で表現できます。 この型は C コンパイラでは広くはサポートされていません: たいていのマシンでは、保存するのに unsigned short が使えますが、数学の演算には使えません。 詳しいことは Wikipedia の half-precision floating-point format のページを参照してください。

  7. When packing, 'x' inserts one NUL byte.

  8. フォーマット文字 'p' は "Pascal 文字列 (pascal string)" をコードします。Pascal 文字列は count で与えられる 固定長のバイト列 に収められた短い可変長の文字列です。このデータの先頭の 1 バイトには文字列の長さか255 のうち、小さい方の数が収められます。その後に文字列のバイトデータが続きます。 pack() に渡された Pascal 文字列の長さが長すぎた (count-1 よりも長い) 場合、先頭の count-1 バイトが書き込まれます。文字列が count-1 よりも短い場合、指定した count バイトに達するまでの残りの部分はヌルで埋められます。 unpack() では、フォーマット文字 'p' は指定された count バイトだけデータを読み込みますが、返される文字列は決して 255 文字を超えることはないので注意してください。

  9. For the 's' format character, the count is interpreted as the length of the bytes, not a repeat count like for the other format characters; for example, '10s' means a single 10-byte string mapping to or from a single Python byte string, while '10c' means 10 separate one byte character elements (e.g., cccccccccc) mapping to or from ten different Python byte objects. (See 使用例 for a concrete demonstration of the difference.) If a count is not given, it defaults to 1. For packing, the string is truncated or padded with null bytes as appropriate to make it fit. For unpacking, the resulting bytes object always has exactly the specified number of bytes. As a special case, '0s' means a single, empty string (while '0c' means 0 characters).

フォーマット文字の前に整数をつけ、繰り返し回数 (count) を指定することができます。例えば、フォーマット文字列 '4h''hhhh' と全く同じ意味です。

フォーマット文字間の空白文字は無視されます; count とフォーマット文字の間にはスペースを入れてはいけません。

整数フォーマット ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q') のいずれかを使って値 x をパックするとき x がフォーマットの適切な値の範囲に無い場合、 struct.error が送出されます。

バージョン 3.1 で変更: 以前は、いくつかの整数フォーマットが適切な範囲にない値を覆い隠して、 struct.error の代わりに DeprecationWarning を送出していました。

'?' フォーマット文字では、返り値は True または False です。パックするときには、引数オブジェクトの論理値としての値が使われます。 0 または 1 のネイティブや標準の真偽値表現でパックされ、アンパックされるときはゼロでない値は True になります。

使用例

注釈

Native byte order examples (designated by the '@' format prefix or lack of any prefix character) may not match what the reader's machine produces as that depends on the platform and compiler.

Pack and unpack integers of three different sizes, using big endian ordering:

>>> from struct import *
>>> pack(">bhl", 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('>bhl')
7

Attempt to pack an integer which is too large for the defined field:

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: 'h' format requires -32768 <= number <= 32767

Demonstrate the difference between 's' and 'c' format characters:

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'

アンパックした結果のフィールドは、変数に割り当てるか named tuple でラップすることによって名前を付けることができます:

>>> record = b'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

The ordering of format characters may have an impact on size in native mode since padding is implicit. In standard mode, the user is responsible for inserting any desired padding. Note in the first pack call below that three NUL bytes were added after the packed '#' to align the following integer on a four-byte boundary. In this example, the output was produced on a little endian machine:

>>> pack('@ci', b'#', 0x12131415)
b'#\x00\x00\x00\x15\x14\x13\x12'
>>> pack('@ic', 0x12131415, b'#')
b'\x15\x14\x13\x12#'
>>> calcsize('@ci')
8
>>> calcsize('@ic')
5

The following format 'llh0l' results in two pad bytes being added at the end, assuming the platform's longs are aligned on 4-byte boundaries:

>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

参考

array モジュール

一様なデータ型からなるバイナリ記録データのパック。

json モジュール

JSON encoder and decoder.

pickle モジュール

Python object serialization.

Applications

Two main applications for the struct module exist, data interchange between Python and C code within an application or another application compiled using the same compiler (native formats), and data interchange between applications using agreed upon data layout (standard formats). Generally speaking, the format strings constructed for these two domains are distinct.

Native Formats

When constructing format strings which mimic native layouts, the compiler and machine architecture determine byte ordering and padding. In such cases, the @ format character should be used to specify native byte ordering and data sizes. Internal pad bytes are normally inserted automatically. It is possible that a zero-repeat format code will be needed at the end of a format string to round up to the correct byte boundary for proper alignment of consective chunks of data.

Consider these two simple examples (on a 64-bit, little-endian machine):

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18

Data is not padded to an 8-byte boundary at the end of the second format string without the use of extra padding. A zero-repeat format code solves that problem:

>>> calcsize('@llh0l')
24

The 'x' format code can be used to specify the repeat, but for native formats it is better to use a zero-repeat format like '0l'.

By default, native byte ordering and alignment is used, but it is better to be explicit and use the '@' prefix character.

Standard Formats

When exchanging data beyond your process such as networking or storage, be precise. Specify the exact byte order, size, and alignment. Do not assume they match the native order of a particular machine. For example, network byte order is big-endian, while many popular CPUs are little-endian. By defining this explicitly, the user need not care about the specifics of the platform their code is running on. The first character should typically be < or > (or !). Padding is the responsibility of the programmer. The zero-repeat format character won't work. Instead, the user must explicitly add 'x' pad bytes where needed. Revisiting the examples from the previous section, we have:

>>> calcsize('<qh6xq')
24
>>> pack('<qh6xq', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack('<qqh', 1, 2, 3)
True
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
True

The above results (executed on a 64-bit machine) aren't guaranteed to match when executed on different machines. For example, the examples below were executed on a 32-bit machine:

>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
False

クラス

struct モジュールは次の型を定義します:

class struct.Struct(format)

フォーマット文字列 format に従ってバイナリデータを読み書きする、新しい Struct オブジェクトを返します。 Struct オブジェクトを一度作ってからそのメソッドを呼び出すと、フォーマット文字列のコンパイルが一度だけになるので、モジュールレベルの関数を同じフォーマットで呼び出すよりも効率的です。

注釈

The compiled versions of the most recent format strings passed to Struct and the module-level functions are cached, so programs that use only a few format strings needn't worry about reusing a single Struct instance.

コンパイルされた Struct オブジェクトは以下のメソッドと属性をサポートします:

pack(v1, v2, ...)

pack() 関数と同じ、コンパイルされたフォーマットを利用するメソッドです。 (len(result)size と等しいでしょう)

pack_into(buffer, offset, v1, v2, ...)

pack_into() 関数と同じ、コンパイルされたフォーマットを利用するメソッドです。

unpack(buffer)

unpack() 関数と同じ、コンパイルされたフォーマットを利用するメソッドです。 (buffer のバイト数は size と等しくなければなりません)。

unpack_from(buffer, offset=0)

unpack_from() 関数と同じ、コンパイルされたフォーマットを利用するメソッドです。 (offset を始点とする buffer のバイト数は少なくとも size 以上でなければなりません)。

iter_unpack(buffer)

iter_unpack() 関数と同じ、コンパイルされたフォーマットを利用するメソッドです。 (buffer のバイト数は size の倍数でなければなりません)。

バージョン 3.4 で追加.

format

この Struct オブジェクトを作成する時に利用されたフォーマット文字列です。

バージョン 3.7 で変更: The format string type is now str instead of bytes.

size

format 属性に対応する構造体の (従って pack() メソッドによって作成されるバイト列オブジェクトの) サイズです。