Chcę użyć struct.unpack()
aby uzyskać długą wartość z ciągu bajtów w Pythonie 2.7, ale znalazłem jakieś dziwne zachowanie i chciałbym wiedzieć, czy jest to błąd, czy nie, a także, co mogę zrobić, aby go obejść.
Co się dzieje, jest następujące:
import struct
>>> struct.unpack("L","")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 8
To jest oczekiwane zachowanie. Chce 8-bajtowy ciąg do wyodrębnienia 8-bajtowej wartości.
Teraz zmieniam kolejność bajtów na kolejność bajtów sieciowych i otrzymuję następujące informacje:
>>> struct.unpack("!L","")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 4
Nagle potrzebuje tylko 4 bajtów dla 8-bajtowej wartości.
Co się z tym dzieje i co mogę zrobić, aby obejść to?
Odpowiedzi:
1 dla odpowiedzi № 1Chodzi o to, że struct
używa rodzimego komputera long
rozmiar w pierwszym przypadku, i struct
„s” standard long
rozmiar w drugim.
W pierwszym przykładzie nie określasz a kolejność bajtów, rozmiar i specyfikator wyrównania (jeden z @=<>!
) więc struct
zakłada "@"
, który używa wartości rodzimych komputera, a mianowicie rodzimego komputera long
rozmiar. Aby być spójnym na różnych platformach, struct
definiuje standardowe rozmiary dla każdego typu, które mogą różnić się od rodzimych rozmiarów twojej maszyny. Każdy specyfikator z wyjątkiem "@"
używa tych standardowych rozmiarów.
Tak więc w przypadku long
, struct
„Standard ma 4 bajty, dlatego "!L"
(lub dowolny "[=<>!]L"
oczekuje 4 bajtów. Jednak natywna maszyna long
najwyraźniej 8 bajtów, dlatego "@L"
lub "L"
oczekuje 8. Jeśli chcesz korzystać z rodzimej kolejności bajtów komputera, ale nadal być kompatybilny struct
„Standardowe rozmiary, polecam określenie wszystkich formatów za pomocą "="
, zamiast pozwolić Pythonowi na domyślne ustawienie "@"
.
Możesz sprawdzić oczekiwany rozmiar struct.calcsize
, tj .:
>>> struct.calcsize("@L"), struct.calcsize("=L")
(to wraca (4, 4)
na moim 64-bitowym komputerze z systemem Windows 10, ale (8, 4)
na moim 64-bitowym komputerze Ubuntu 16.04.)
Możesz również bezpośrednio sprawdzić rozmiar swojego komputera, kompilując a C
skrypt do sprawdzenia wartości sizeof(long)
, na przykład:
#include <stdio.h>
int main()
{
printf("%li",sizeof(long));
return 0;
}
podążałem ten przewodnik skompilować C
skrypt na moim komputerze z systemem Windows 10.