Giả sử bạn cần đọc một tệp nhị phân chứa dữ liệu về các khu vực đô thị, được tạo bởi một chương trình trong C với một bản ghi được định nghĩa là
ví dụ 1. Khu vực tàu điện ngầm. cấu trúc trong ngôn ngữ C
struct MetroArea {
int year;
char name[12];
char country[2];
float population;
};
Đây là cách đọc một bản ghi ở định dạng đó, sử dụng struct.unpack
ví dụ 2. Đọc cấu trúc C trong bảng điều khiển Python
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
Lưu ý cách unpack
trả về một bộ có bốn trường, như được chỉ định bởi chuỗi FORMAT
. Các chữ cái và số trong FORMAT
được mô tả trong tài liệu mô-đun struct
'i12s2sf'
. partizeC typePython giới hạn cho nội dung thực tế>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
04 byte
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
1>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
132 bit;
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
312 byte
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
4>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
5chiều dài = 12
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
62 byte
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
7>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
5chiều dài = 2
>>> from struct import unpack, calcsize
>>> FORMAT = 'i12s2sf'
>>> size = calcsize[FORMAT]
>>> data = open['metro_areas.bin', 'rb'].read[size]
>>> data
b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L"
>>> unpack[FORMAT, data]
[2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
94 byte
$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
0$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
032-bit; . 4×1038
Một chi tiết về bố cục của
$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
2 không rõ ràng trong mã trong. kích thước không phải là sự khác biệt duy nhất giữa các trường $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
3 và $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
4. Trường $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
4 luôn chứa mã quốc gia gồm 2 chữ cái, nhưng $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
3 là một chuỗi có tận cùng bằng không có tối đa 12 byte bao gồm cả _____12_______7 kết thúc—mà bạn có thể nhìn thấy ngay sau từ $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
8Bây giờ, hãy xem lại một kịch bản để trích xuất tất cả các bản ghi từ
$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
2 và tạo một báo cáo đơn giản như thế này$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
giới thiệu chức năng
from struct import iter_unpack
FORMAT = 'i12s2sf' # [1]
def text[field: bytes] -> str: # [2]
octets = field.split[b'\0', 1][0] # [3]
return octets.decode['cp437'] # [4]
with open['metro_areas.bin', 'rb'] as fp: # [5]
data = fp.read[]
for fields in iter_unpack[FORMAT, data]: # [6]
year, name, country, pop = fields
place = text[name] + ', ' + text[country] # [7]
print[f'{year}\t{place}\t{pop:,.0f}']
0 tiện dụngví dụ 3. tàu điện ngầm. py. liệt kê tất cả các bản ghi từ
$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
2from struct import iter_unpack
FORMAT = 'i12s2sf' # [1]
def text[field: bytes] -> str: # [2]
octets = field.split[b'\0', 1][0] # [3]
return octets.decode['cp437'] # [4]
with open['metro_areas.bin', 'rb'] as fp: # [5]
data = fp.read[]
for fields in iter_unpack[FORMAT, data]: # [6]
year, name, country, pop = fields
place = text[name] + ', ' + text[country] # [7]
print[f'{year}\t{place}\t{pop:,.0f}']
Định dạng
struct
Chức năng tiện ích để giải mã và dọn sạch các trường
5;>>> from struct import unpack, calcsize >>> FORMAT = 'i12s2sf' >>> size = calcsize[FORMAT] >>> data = open['metro_areas.bin', 'rb'].read[size] >>> data b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L" >>> unpack[FORMAT, data] [2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
Xử lý chuỗi C kết thúc null. tách một lần vào ngày
7, sau đó lấy phần đầu tiên$ python3 metro_read.py 2018 Tokyo, JP 43,868,228 2015 Shanghai, CN 38,700,000 2015 Jakarta, ID 31,689,592
Giải mã
5 thành>>> from struct import unpack, calcsize >>> FORMAT = 'i12s2sf' >>> size = calcsize[FORMAT] >>> data = open['metro_areas.bin', 'rb'].read[size] >>> data b"\xe2\x07\x00\x00Tokyo\x00\xc5\x05\x01\x00\x00\x00JP\x00\x00\x11X'L" >>> unpack[FORMAT, data] [2018, b'Tokyo\x00\xc5\x05\x01\x00\x00\x00', b'JP', 43868228.0]
4from struct import iter_unpack FORMAT = 'i12s2sf' # [1] def text[field: bytes] -> str: # [2] octets = field.split[b'\0', 1][0] # [3] return octets.decode['cp437'] # [4] with open['metro_areas.bin', 'rb'] as fp: # [5] data = fp.read[] for fields in iter_unpack[FORMAT, data]: # [6] year, name, country, pop = fields place = text[name] + ', ' + text[country] # [7] print[f'{year}\t{place}\t{pop:,.0f}']
Mở và đọc toàn bộ tệp ở chế độ nhị phân;
struct.unpack
0 trả về một trình tạo tạo ra một bộ trường cho mỗi chuỗi byte khớp với chuỗi định dạngCác trường
3 và$ python3 metro_read.py 2018 Tokyo, JP 43,868,228 2015 Shanghai, CN 38,700,000 2015 Jakarta, ID 31,689,592
4 cần xử lý thêm bằng hàm$ python3 metro_read.py 2018 Tokyo, JP 43,868,228 2015 Shanghai, CN 38,700,000 2015 Jakarta, ID 31,689,592
struct.unpack
3
Mô-đun struct
không cung cấp cách nào để chỉ định các trường chuỗi kết thúc null. Khi xử lý một trường như
$ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
3 trong ví dụ trên, sau khi giải nén chúng ta cần kiểm tra các byte trả về để loại bỏ $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
7 đầu tiên và tất cả các byte sau nó trong trường đó. Rất có thể các byte sau $ python3 metro_read.py
2018 Tokyo, JP 43,868,228
2015 Shanghai, CN 38,700,000
2015 Jakarta, ID 31,689,592
7 đầu tiên và cho đến cuối trường là rác. Bạn thực sự có thể thấy điều đó trongChế độ xem bộ nhớ có thể giúp thử nghiệm và gỡ lỗi chương trình bằng cách sử dụng struct
dễ dàng hơn, như phần tiếp theo sẽ giải thích