Pythonは、「BH」のフォーマットコードには4バイトが必要だと言っています。
struct.error: unpack requires a string argument of length 4
ここにコードがあり、必要だと思うので3バイトを入れています:
major, minor = struct.unpack("BH", self.fp.read(3))
"B"符号なしchar(1バイト)+ "H"符号なしshort(2バイト)= 3バイト(!?)
struct.calcsize( "BH")は4バイトを言います。
編集:ファイルは〜800 MBであり、これはファイルの最初の数バイトにあるので、データがまだ読み取られていないことを確信しています。
StructモジュールはC構造体を模倣します。プロセッサが奇数アドレスの16ビットワードまたは4で割り切れないアドレスの32ビットワードを読み取るには、より多くのCPUサイクルが必要なため、構造体は「パッドバイト」を追加して、構造体のメンバーを自然境界に分類します。考慮してください:
struct { 11
char a; 012345678901
short b; ------------
char c; axbbcxxxdddd
int d;
};
この構造は、12バイトのメモリを占有します(xはパッドバイトです)。
Pythonも同様に機能します( struct ドキュメントを参照):
>>> import struct
>>> struct.pack('BHBL',1,2,3,4)
'\x01\x00\x02\x00\x03\x00\x00\x00\x04\x00\x00\x00'
>>> struct.calcsize('BHBL')
12
コンパイラには通常、パディングを排除する方法があります。 Pythonでは、= <>!のいずれか!パディングを削除します:
>>> struct.calcsize('=BHBL')
8
>>> struct.pack('=BHBL',1,2,3,4)
'\x01\x02\x00\x03\x04\x00\x00\x00'
構造体にパディングを処理させることに注意してください。 Cでは、これらの構造:
struct A { struct B {
short a; int a;
char b; char b;
}; };
通常、それぞれ4バイトと8バイトです。構造が配列で使用される場合、構造の最後にパディングが発生します。これにより、配列の後半の構造の正しい境界に「a」メンバーが整列されます。 Pythonのstructモジュールは最後にパディングしません:
>>> struct.pack('LB',1,2)
'\x01\x00\x00\x00\x02'
>>> struct.pack('LBLB',1,2,3,4)
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04'
デフォルトでは、多くのプラットフォームでshortは2の倍数のオフセットに揃えられるため、charの後にパディングバイトが追加されます。
これを無効にするには、struct.unpack("=BH", data)
を使用します。これは、パディングを追加しない標準の配置を使用します。
>>> struct.calcsize('=BH')
3
=
文字は、ネイティブのバイト順を使用します。 <
の代わりに>
または=
を使用して、それぞれリトルエンディアンまたはビッグエンディアンのバイト順を強制することもできます。