Chúng ta có thể tạo cấu trúc bằng Python không?

Mô-đun này chuyển đổi giữa các giá trị Python và cấu trúc C được biểu diễn dưới dạng các đối tượng Python. Rút gọn mô tả các chuyển đổi dự định sang/từ các giá trị Python. Các chức năng và đối tượng của mô-đun có thể được sử dụng cho hai ứng dụng phần lớn là khác biệt, trao đổi dữ liệu với các nguồn bên ngoài (tệp hoặc kết nối mạng) hoặc truyền dữ liệu giữa ứng dụng Python và lớp C

Ghi chú

Khi không có ký tự tiền tố nào được cung cấp, chế độ gốc là mặc định. Nó đóng gói hoặc giải nén dữ liệu dựa trên nền tảng và trình biên dịch mà trình thông dịch Python được xây dựng trên đó. Kết quả của việc đóng gói một cấu trúc C nhất định bao gồm các byte đệm duy trì sự liên kết phù hợp cho các loại C có liên quan; . Ngược lại, khi truyền dữ liệu giữa các nguồn bên ngoài, lập trình viên chịu trách nhiệm xác định thứ tự byte và phần đệm giữa các phần tử. Xem để biết chi tiết

Một số hàm (và phương thức của ) nhận đối số bộ đệm. Điều này đề cập đến các đối tượng thực hiện và cung cấp bộ đệm có thể đọc được hoặc có thể ghi được. Các loại phổ biến nhất được sử dụng cho mục đích đó là và, nhưng nhiều loại khác có thể được xem như một mảng byte thực hiện giao thức bộ đệm, để chúng có thể được đọc/điền mà không cần sao chép thêm từ một đối tượng

Chức năng và ngoại lệ

Mô-đun xác định các chức năng và ngoại lệ sau

ngoại lệ cấu trúc. lỗi

Ngoại lệ được đưa ra vào những dịp khác nhau;

cấu trúc. gói(định dạng , v1 . , v2, ...)

Trả về đối tượng bytes chứa các giá trị v1, v2,… được đóng gói theo định dạng chuỗi định dạng. Các đối số phải khớp chính xác với các giá trị theo yêu cầu của định dạng

cấu trúc. pack_into(định dạng , bộ đệm . , offset, v1, v2, ...)

Đóng gói các giá trị v1, v2, … theo định dạng chuỗi định dạng và ghi các byte đã đóng gói vào bộ đệm đệm có thể ghi bắt đầu từ vị trí offset. Lưu ý rằng offset là đối số bắt buộc

cấu trúc. giải nén(định dạng , bộ đệm)

Giải nén từ bộ đệm đệm (có lẽ được đóng gói bởi

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
7) theo định dạng chuỗi định dạng. Kết quả là một bộ ngay cả khi nó chứa chính xác một mục. Kích thước của bộ đệm theo byte phải khớp với kích thước theo yêu cầu của định dạng, như được phản ánh bởi

cấu trúc. unpack_from(định dạng , /, buffer, offset=0)

Giải nén từ bộ đệm bắt đầu từ vị trí offset, theo định dạng chuỗi định dạng. Kết quả là một bộ ngay cả khi nó chứa chính xác một mục. Kích thước của bộ đệm tính bằng byte, bắt đầu từ vị trí bù, ít nhất phải bằng kích thước theo yêu cầu của định dạng, như được phản ánh bởi

cấu trúc. iter_unpack(định dạng , bộ đệm)

Lặp lại giải nén từ bộ đệm đệm theo định dạng chuỗi định dạng. Hàm này trả về một trình vòng lặp sẽ đọc các khối có kích thước bằng nhau từ bộ đệm cho đến khi tất cả nội dung của nó được sử dụng hết. Kích thước của bộ đệm theo byte phải là bội số của kích thước theo yêu cầu của định dạng, như được phản ánh bởi

Mỗi lần lặp tạo ra một bộ như được chỉ định bởi chuỗi định dạng

Mới trong phiên bản 3. 4

cấu trúc. kích thước tính toán(định dạng)

Trả về kích thước của cấu trúc (và do đó của đối tượng byte được tạo bởi

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
7) tương ứng với định dạng chuỗi định dạng

định dạng chuỗi

Chuỗi định dạng mô tả bố cục dữ liệu khi đóng gói và giải nén dữ liệu. Chúng được xây dựng từ , chỉ định loại dữ liệu được đóng gói/giải nén. Ngoài ra, các ký tự đặc biệt điều khiển. Mỗi chuỗi định dạng bao gồm một ký tự tiền tố tùy chọn mô tả các thuộc tính tổng thể của dữ liệu và một hoặc nhiều ký tự định dạng mô tả các giá trị dữ liệu thực tế và phần đệm

Thứ tự byte, kích thước và căn chỉnh

Theo mặc định, các loại C được thể hiện ở định dạng gốc và thứ tự byte của máy và được căn chỉnh chính xác bằng cách bỏ qua các byte đệm nếu cần (theo quy tắc được sử dụng bởi trình biên dịch C). Hành vi này được chọn sao cho các byte của cấu trúc được đóng gói tương ứng chính xác với bố cục bộ nhớ của cấu trúc C tương ứng. Việc sử dụng thứ tự byte gốc và đệm hoặc định dạng tiêu chuẩn hay không tùy thuộc vào ứng dụng

Ngoài ra, ký tự đầu tiên của chuỗi định dạng có thể được sử dụng để biểu thị thứ tự byte, kích thước và căn chỉnh của dữ liệu được đóng gói, theo bảng sau

Nhân vật

thứ tự byte

Kích thước

căn chỉnh

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

tự nhiên

tự nhiên

tự nhiên

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

tự nhiên

Tiêu chuẩn

không ai

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

người tí hon

Tiêu chuẩn

không ai

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

người lớn

Tiêu chuẩn

không ai

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

mạng (= big-endian)

Tiêu chuẩn

không ai

Nếu ký tự đầu tiên không phải là một trong số này, thì

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
7 được giả định

Thứ tự byte gốc là big-endian hoặc little-endian, tùy thuộc vào hệ thống máy chủ. Ví dụ: Intel x86, AMD64 (x86-64) và Apple M1 là ít cấp cuối; . Sử dụng để kiểm tra độ bền của hệ thống của bạn

Kích thước gốc và căn chỉnh được xác định bằng cách sử dụng biểu thức

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
9 của trình biên dịch C. Điều này luôn được kết hợp với thứ tự byte gốc

Kích thước tiêu chuẩn chỉ phụ thuộc vào ký tự định dạng;

Lưu ý sự khác biệt giữa

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
7 và
>>> 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)
1. cả hai đều sử dụng thứ tự byte gốc, nhưng kích thước và căn chỉnh của cái sau được chuẩn hóa

Biểu mẫu

>>> 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)
2 biểu thị thứ tự byte mạng luôn là big-endian như được định nghĩa trong IETF RFC 1700

Không có cách nào để chỉ ra thứ tự byte không có nguồn gốc (bắt buộc hoán đổi byte);

ghi chú

  1. Phần đệm chỉ được thêm tự động giữa các thành viên cấu trúc liên tiếp. Không có phần đệm nào được thêm vào đầu hoặc cuối cấu trúc được mã hóa

  2. No padding is added when using non-native size and alignment, e.g. with ‘<’, ‘>’, ‘=’, and ‘!’.

  3. Để căn chỉnh phần cuối của cấu trúc theo yêu cầu căn chỉnh của một loại cụ thể, hãy kết thúc định dạng bằng mã cho loại đó với số lần lặp lại bằng 0. Thấy

định dạng ký tự

Các ký tự định dạng có ý nghĩa như sau; . Cột 'Kích thước tiêu chuẩn' đề cập đến kích thước của giá trị được đóng gói tính bằng byte khi sử dụng kích thước tiêu chuẩn; . Khi sử dụng kích thước gốc, kích thước của giá trị được đóng gói phụ thuộc vào nền tảng

Sự sắp xếp

Loại C

loại trăn

kích thước tiêu chuẩn

ghi chú

>>> 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)
9

byte đệm

không có giá trị

(7)

>>> 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
0

than

byte có độ dài 1

1

>>> 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
1

đã ký ký tự

số nguyên

1

(1), (2)

>>> 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
2

không dấu ký tự

số nguyên

1

(2)

>>> 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
3

_Bool

bool

1

(1)

>>> 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
4

ngắn ngủi

số nguyên

2

(2)

>>> 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
5

không dấu ngắn

số nguyên

2

(2)

>>> 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
6

int

số nguyên

4

(2)

>>> 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
7

không dấu int

số nguyên

4

(2)

>>> 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
8

Dài

số nguyên

4

(2)

>>> 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
9

không dấu dài

số nguyên

4

(2)

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

dài dài

số nguyên

8

(2)

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

không dấu dài dài

số nguyên

8

(2)

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

size_t

số nguyên

(3)

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

size_t

số nguyên

(3)

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

(6)

trôi nổi

2

(4)

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

trôi nổi

trôi nổi

4

(4)

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

gấp đôi

trôi nổi

8

(4)

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

char[]

byte

(9)

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

char[]

byte

(số 8)

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

khoảng trống*

số nguyên

(5)

Đã thay đổi trong phiên bản 3. 3. Đã thêm hỗ trợ cho các định dạng

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18
0 và
>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18
1.

Đã thay đổi trong phiên bản 3. 6. Đã thêm hỗ trợ cho định dạng

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

ghi chú

  1. Mã chuyển đổi

    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    3 tương ứng với loại _Bool được xác định bởi C99. Nếu loại này không có sẵn, thì nó được mô phỏng bằng cách sử dụng char . Ở chế độ tiêu chuẩn, nó luôn được biểu thị bằng một byte.

  2. Khi cố gắng đóng gói một số không phải là số nguyên bằng cách sử dụng bất kỳ mã chuyển đổi số nguyên nào, nếu số không phải là số nguyên có phương thức

    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    4 thì phương thức đó được gọi để chuyển đổi đối số thành số nguyên trước khi đóng gói

    Đã thay đổi trong phiên bản 3. 2. Đã thêm việc sử dụng phương thức

    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    4 cho các số không phải số nguyên.

  3. Mã chuyển đổi

    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    0 và
    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    1 chỉ khả dụng cho kích thước gốc (được chọn làm mặc định hoặc với ký tự thứ tự byte
    >>> pack("@ccc", b'1', b'2', b'3')
    b'123'
    >>> pack("@3s", b'123')
    b'123'
    
    7). Đối với kích thước tiêu chuẩn, bạn có thể sử dụng bất kỳ định dạng số nguyên nào khác phù hợp với ứng dụng của mình

  4. Đối với mã chuyển đổi

    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    9,
    >>> calcsize('@llh0l')
    24
    
    0 và
    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    2, biểu diễn đóng gói sử dụng định dạng IEEE 754 nhị phân32, nhị phân64 hoặc nhị phân16 (tương ứng cho ____39_______9, ____49_______0 hoặc _
    >>> calcsize('@lhl')
    24
    >>> calcsize('@llh')
    18
    
    2), bất kể định dạng dấu phẩy động được sử dụng bởi nền tảng

  5. Ký tự định dạng

    >>> calcsize('@llh0l')
    24
    
    5 chỉ khả dụng cho thứ tự byte gốc (được chọn làm mặc định hoặc với ký tự thứ tự byte
    >>> pack("@ccc", b'1', b'2', b'3')
    b'123'
    >>> pack("@3s", b'123')
    b'123'
    
    7). Ký tự thứ tự byte
    >>> 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)
    
    1 chọn sử dụng thứ tự little-endian hoặc big-endian dựa trên hệ thống máy chủ. Mô-đun cấu trúc không diễn giải đây là thứ tự gốc, vì vậy định dạng
    >>> calcsize('@llh0l')
    24
    
    5 không khả dụng

  6. Loại "chính xác một nửa" của IEEE 754 nhị phân16 được giới thiệu trong bản sửa đổi năm 2008 của tiêu chuẩn IEEE 754. Nó có bit dấu, số mũ 5 bit và độ chính xác 11 bit (với 10 bit được lưu trữ rõ ràng) và có thể biểu thị các số trong khoảng từ khoảng

    >>> calcsize('@llh0l')
    24
    
    9 đến
    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    0 với độ chính xác đầy đủ. Loại này không được trình biên dịch C hỗ trợ rộng rãi. trên một máy thông thường, một ký tự ngắn không dấu có thể được sử dụng để lưu trữ, nhưng không dùng cho các phép toán. Xem trang Wikipedia về định dạng dấu chấm động nửa chính xác để biết thêm thông tin

  7. Khi đóng gói, _______ 59 _______ 1 chèn một byte NULL

  8. Ký tự định dạng

    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    2 mã hóa một “chuỗi Pascal”, nghĩa là một chuỗi ngắn có độ dài thay đổi được lưu trữ trong một số byte cố định, được cung cấp bởi số đếm. Byte đầu tiên được lưu trữ là độ dài của chuỗi hoặc 255, tùy theo giá trị nào nhỏ hơn. Các byte của chuỗi theo sau. Nếu chuỗi được truyền vào quá dài (dài hơn số đếm trừ đi 1), thì chỉ có _______59_______4 byte đầu của chuỗi được lưu trữ. Nếu chuỗi ngắn hơn
    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    4, nó sẽ được đệm bằng các byte rỗng để sử dụng chính xác các byte đếm được trong tất cả. Lưu ý rằng đối với , ký tự định dạng
    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    2 tiêu thụ
    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    8 byte, nhưng chuỗi được trả về không bao giờ được chứa nhiều hơn 255 byte

  9. Đối với ký tự định dạng

    >>> calcsize(')
    24
    >>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
    True
    >>> calcsize('@llh')
    18
    >>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
    True
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    24
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    True
    
    9, số đếm được hiểu là độ dài của byte, không phải là số đếm lặp lại như đối với các ký tự định dạng khác; . g. ,
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    12
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    False
    
    2) ánh xạ tới hoặc từ mười đối tượng byte Python khác nhau. (Xem để có một minh chứng cụ thể về sự khác biệt. ) Nếu số đếm không được đưa ra, nó sẽ mặc định là 1. Để đóng gói, chuỗi được cắt bớt hoặc đệm bằng các byte rỗng nếu thích hợp để làm cho nó vừa vặn. Để giải nén, đối tượng byte kết quả luôn có chính xác số byte đã chỉ định. Trong trường hợp đặc biệt,
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    12
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    False
    
    3 có nghĩa là một chuỗi trống, đơn (trong khi
    >>> calcsize(')
    24
    >>> calcsize('@llh0l')
    12
    >>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
    False
    
    4 có nghĩa là 0 ký tự)

Một ký tự định dạng có thể được bắt đầu bằng một số lặp tích phân. Ví dụ: chuỗi định dạng

>>> calcsize(')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
False
5 có nghĩa hoàn toàn giống với
>>> calcsize(')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
False
6

Các ký tự khoảng trắng giữa các định dạng bị bỏ qua;

Khi đóng gói một giá trị

>>> 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)
9 sử dụng một trong các định dạng số nguyên (
>>> calcsize(')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
False
8,
>>> calcsize(')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
False
9,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
00,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
01,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
02,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
03,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
04,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
05,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
06,
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
07), nếu
>>> 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)
9 nằm ngoài phạm vi hợp lệ cho định dạng đó thì sẽ được nâng lên

Đã thay đổi trong phiên bản 3. 1. Trước đây, một số định dạng số nguyên bao bọc các giá trị nằm ngoài phạm vi và tăng thay vì.

Đối với ký tự định dạng

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18
3, giá trị trả về là hoặc. Khi đóng gói, giá trị thực của đối tượng đối số được sử dụng. 0 hoặc 1 trong biểu diễn bool gốc hoặc tiêu chuẩn sẽ được đóng gói và bất kỳ giá trị khác không nào sẽ là
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
13 khi giải nén

ví dụ

Ghi chú

Các ví dụ về thứ tự byte gốc (được chỉ định bởi tiền tố định dạng

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
7 hoặc thiếu bất kỳ ký tự tiền tố nào) có thể không khớp với những gì máy của người đọc tạo ra vì điều đó phụ thuộc vào nền tảng và trình biên dịch

Đóng gói và giải nén các số nguyên có ba kích thước khác nhau, sử dụng thứ tự big endian

>>> 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

Cố gắng đóng gói một số nguyên quá lớn đối với trường đã xác định

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

Minh họa sự khác biệt giữa ký tự định dạng

>>> calcsize(')
24
>>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
True
>>> calcsize(')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
True
9 và
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
18

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

Các trường đã giải nén có thể được đặt tên bằng cách gán chúng cho các biến hoặc bằng cách gói kết quả vào một bộ dữ liệu được đặt tên

>>> 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)

Thứ tự của các ký tự định dạng có thể ảnh hưởng đến kích thước ở chế độ gốc do phần đệm ẩn. Ở chế độ tiêu chuẩn, người dùng chịu trách nhiệm chèn bất kỳ phần đệm mong muốn nào. Lưu ý trong lệnh gọi

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
19 đầu tiên bên dưới rằng ba byte NUL đã được thêm vào sau
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
20 được đóng gói để căn chỉnh số nguyên sau trên ranh giới bốn byte. Trong ví dụ này, đầu ra được sản xuất trên một máy endian nhỏ

>>> 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

Định dạng sau đây

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
21 dẫn đến hai byte đệm được thêm vào cuối, giả sử thời gian dài của nền tảng được căn chỉnh trên ranh giới 4 byte

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

Xem thêm

mô-đun

Lưu trữ nhị phân được đóng gói của dữ liệu đồng nhất

mô-đun

Bộ mã hóa và giải mã JSON

mô-đun

Tuần tự hóa đối tượng Python

Các ứng dụng

Có hai ứng dụng chính cho mô-đun, trao đổi dữ liệu giữa Python và mã C trong một ứng dụng hoặc ứng dụng khác được biên dịch bằng cùng một trình biên dịch () và trao đổi dữ liệu giữa các ứng dụng bằng cách sử dụng bố cục dữ liệu đã thỏa thuận (). Nói chung, các chuỗi định dạng được xây dựng cho hai miền này là khác biệt

Định dạng gốc

Khi xây dựng các chuỗi định dạng bắt chước bố cục gốc, trình biên dịch và kiến ​​trúc máy xác định thứ tự byte và phần đệm. Trong những trường hợp như vậy, nên sử dụng ký tự định dạng

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
2 để chỉ định thứ tự byte gốc và kích thước dữ liệu. Các byte đệm bên trong thường được chèn tự động. Có thể cần một mã định dạng không lặp lại ở cuối chuỗi định dạng để làm tròn đến ranh giới byte chính xác để căn chỉnh chính xác các khối dữ liệu liên tiếp

Hãy xem xét hai ví dụ đơn giản này (trên máy 64-bit, little endian)

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

Dữ liệu không được đệm vào ranh giới 8 byte ở cuối chuỗi định dạng thứ hai mà không sử dụng phần đệm bổ sung. Mã định dạng không lặp lại giải quyết vấn đề đó

>>> calcsize('@llh0l')
24

Mã định dạng

>>> calcsize(')
24
>>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
True
>>> calcsize(')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
True
1 có thể được sử dụng để chỉ định lặp lại, nhưng đối với các định dạng gốc, tốt hơn là sử dụng định dạng không lặp lại như
>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
28

Theo mặc định, thứ tự và căn chỉnh byte gốc được sử dụng, nhưng tốt hơn là nên rõ ràng và sử dụng ký tự tiền tố

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

định dạng tiêu chuẩn

Khi trao đổi dữ liệu ngoài quy trình của bạn, chẳng hạn như kết nối mạng hoặc lưu trữ, hãy chính xác. Chỉ định thứ tự byte, kích thước và căn chỉnh chính xác. Đừng cho rằng chúng khớp với thứ tự gốc của một máy cụ thể. Ví dụ: thứ tự byte mạng là big-endian, trong khi nhiều CPU phổ biến là little-endian. Bằng cách xác định điều này một cách rõ ràng, người dùng không cần quan tâm đến các chi tiết cụ thể của nền tảng mà mã của họ đang chạy trên đó. Ký tự đầu tiên thường phải là

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
4 hoặc
>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
5 (hoặc
>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
6). Đệm là trách nhiệm của lập trình viên. Ký tự định dạng không lặp lại sẽ không hoạt động. Thay vào đó, người dùng phải thêm rõ ràng
>>> calcsize(')
24
>>> pack(', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack(', 1, 2, 3)
True
>>> calcsize(')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack(', 1, 2, 3)
True
1 byte đệm khi cần. Xem lại các ví dụ ở phần trước, ta có

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

Các kết quả trên (được thực thi trên máy 64 bit) không được đảm bảo khớp khi thực hiện trên các máy khác nhau. Ví dụ: các ví dụ bên dưới được thực thi trên máy 32 bit

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

Các lớp học

Mô-đun này cũng xác định loại sau

lớp cấu trúc. Cấu trúc(định dạng)

Trả về một đối tượng Struct mới ghi và đọc dữ liệu nhị phân theo định dạng chuỗi định dạng. Tạo một đối tượng

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
3 một lần và gọi các phương thức của nó hiệu quả hơn gọi các hàm cấp mô-đun có cùng định dạng vì chuỗi định dạng chỉ được biên dịch một lần

Ghi chú

Các phiên bản đã biên dịch của các chuỗi định dạng gần đây nhất được chuyển đến và các chức năng cấp mô-đun được lưu vào bộ đệm, vì vậy các chương trình chỉ sử dụng một vài chuỗi định dạng không cần phải lo lắng về việc sử dụng lại một phiên bản duy nhất

Các đối tượng Struct đã biên dịch hỗ trợ các phương thức và thuộc tính sau

pack(v1 , v2, ...)

Giống với chức năng, sử dụng định dạng được biên dịch. (

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "", line 1, in 
struct.error: 'h' format requires -32768 <= number <= 32767
39 sẽ bằng. )

pack_into(bộ đệm , , v1, v2, ...)

Giống với chức năng, sử dụng định dạng được biên dịch

giải nén(bộ đệm)

Giống với chức năng, sử dụng định dạng được biên dịch. Kích thước của bộ đệm theo byte phải bằng

unpack_from(bộ đệm , =0)

Giống với chức năng, sử dụng định dạng được biên dịch. Kích thước của bộ đệm tính theo byte, bắt đầu từ vị trí bù, ít nhất phải bằng

iter_unpack(bộ đệm)

Giống với chức năng, sử dụng định dạng được biên dịch. Kích thước của bộ đệm theo byte phải là bội số của

Mới trong phiên bản 3. 4

định dạng

Chuỗi định dạng được sử dụng để xây dựng đối tượng Struct này

Đã thay đổi trong phiên bản 3. 7. Kiểu chuỗi định dạng bây giờ thay vì.

kích thước

Kích thước được tính toán của cấu trúc (và do đó của đối tượng byte do phương thức tạo ra) tương ứng với

Python có cấu trúc như C++ không?

. lớp Cấu trúc (đối tượng). vượt qua s = Struct() s. a = 5 bản in. a) in 5.

Cấu trúc có nghĩa là gì trong Python?

Chúng ta cần xem xét cách tận dụng tốt nhất các tính năng của Python để tạo mã rõ ràng, hiệu quả. Về mặt thực tế, “cấu trúc” có nghĩa là tạo mã sạch có logic và các thành phần phụ thuộc rõ ràng cũng như cách các tệp và thư mục được tổ chức trong hệ thống tệp .

Cấu trúc được gọi trong Python là gì?

Cấu trúc trong Python được sử dụng để thực hiện chuyển đổi cấu trúc C (được biểu diễn dưới dạng đối tượng byte Python ) thành Python . Cấu trúc trong Python được sử dụng để xử lý tệp trong trường hợp dữ liệu được lưu trữ nhị phân. Việc chuyển đổi cấu trúc C sang dạng Python được thực hiện bằng cách sử dụng chuỗi định dạng.

Python có cấu trúc dữ liệu tích hợp sẵn không?

Python có bốn cấu trúc dữ liệu sẵn có không nguyên thủy là Danh sách, Từ điển, Tuple và Tập hợp . Chúng gần như bao gồm 80% cấu trúc dữ liệu trong thế giới thực của chúng tôi.