In addition to being more complicated to read, this version also requires a lot more
work, as it performs various offset calculations, copies data, and makes small slice ob‐
jects. If you’re going to be unpacking a lot of structures from a large byte string you’ve
already read, unpack_from() is a more elegant approach.
Unpacking records is one place where you might want to use namedtuple objects from
the collections module. This allows you to set attribute names on the returned tuples.
For example:
from collections import namedtuple
Record = namedtuple('Record', ['kind','x','y'])
with open('data.p''rb'as f:
records = (Record(*rfor r in read_records('<idd'f))
for r in records:
print(r.kindr.xr.y)
If you’re writing a program that needs to work with a large amount of binary data, you
may be better off using a library such as numpy. For example, instead of reading a binary
into a list of tuples, you could read it into a structured array, like this:
>>> import numpy as np
>>> f = open('data.b''rb')
>>> records = np.fromfile(fdtype='<i,<d,<d')
>>> records
array([(1, 2.3, 4.5), (6, 7.8, 9.0), (12, 13.4, 56.7)],
dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', '<f8')])
>>> records[0]
(1, 2.3, 4.5)
>>> records[1]
(6, 7.8, 9.0)
>>>
Last, but not least, if you’re faced with the task of reading binary data in some known
file format (i.e., image formats, shape files, HDF5, etc.), check to see if a Python module
already exists for it. There’s no reason to reinvent the wheel if you don’t have to.
6.12. Reading Nested and Variable-Sized Binary
Structures
Problem
You need to read complicated binary-encoded data that contains a collection of nested
and/or variable-sized records. Such data might include images, video, shapefiles, and
so on.
6.12. Reading Nested and Variable-Sized Binary Structures  |  203
Pdf to word converter sign in - C# PDF File Permission Library: add, remove, update PDF file permission in C#.net, ASP.NET, MVC, WPF
Tell C# users how to set PDF file permissions, like printing, copying, modifying, extracting, annotating, form filling, etc
pdf signature stamp; adding signature to pdf form
Pdf to word converter sign in - VB.NET PDF File Permission Library: add, remove, update PDF file permission in vb.net, ASP.NET, MVC, WPF
VB.NET Tutorial for How to Set PDF File Access Permissions Using XDoc.PDF for .NET
add signature pdf preview; adding signature to pdf doc
Solution
The struct module can be used to decode and encode almost any kind of binary data
structure. To illustrate the kind of data in question here, suppose you have this Python
data structure representing a collection of points that make up a series of polygons:
polys = [
[ (1.02.5), (3.54.0), (2.51.5) ],
[ (7.01.2), (5.13.0), (0.57.5), (0.89.0) ],
[ (3.46.3), (1.20.5), (4.69.2) ],
]
Now suppose this data was to be encoded into a binary file where the file started with
the following header:
Byte Type
Description
0
int
File code (0x1234, little endian)
4
double Minimum x (little endian)
12
double Minimum y (little endian)
20
double Maximum x (little endian)
28
double Maximum y (little endian)
36
int
Number of polygons (little endian)
Following the header, a series of polygon records follow, each encoded as follows:
Byte Type
Description
0
int
Record length including length (N bytes)
4-N
Points Pairs of (X,Y) coords as doubles
To write this file, you can use Python code like this:
import struct
import itertools
def write_polys(filenamepolys):
# Determine bounding box
flattened = list(itertools.chain(*polys))
min_x = min(x for xy in flattened)
max_x = max(x for xy in flattened)
min_y = min(y for xy in flattened)
max_y = max(y for xy in flattened)
with open(filename'wb'as f:
f.write(struct.pack('<iddddi',
0x1234,
min_xmin_y,
max_xmax_y,
len(polys)))
204  |  Chapter 6: Data Encoding and Processing
C# PDF Digital Signature Library: add, remove, update PDF digital
XDoc.HTML5 Viewer. XDoc.Windows Viewer. XDoc.Converter. VB.NET How-to, VB.NET PDF, VB.NET Word, VB.NET Excel, VB Search unsigned signature field in PDF document.
pdf sign; add signature to pdf acrobat
VB.NET PDF Digital Signature Library: add, remove, update PDF
XDoc.HTML5 Viewer. XDoc.Windows Viewer. XDoc.Converter. VB.NET How-to, VB.NET PDF, VB.NET Word, VB.NET Excel, VB Search unsigned signature field in PDF document.
export pdf to word sign in; add signature image to pdf
for poly in polys:
size = len(poly) * struct.calcsize('<dd')
f.write(struct.pack('<i'size+4))
for pt in poly:
f.write(struct.pack('<dd'*pt))
# Call it with our polygon data
write_polys('polys.bin'polys)
To read the resulting data back, you can write very similar looking code using the 
struct.unpack() function, reversing the operations performed during writing. For
example:
import struct
def read_polys(filename):
with open(filename'rb'as f:
# Read the header
header = f.read(40)
file_codemin_x, min_ymax_x, max_y, num_polys = \
struct.unpack('<iddddi'header)
polys = []
for n in range(num_polys):
pbytes= struct.unpack('<i', f.read(4))
poly = []
for m in range(pbytes // 16):
pt = struct.unpack('<dd'f.read(16))
poly.append(pt)
polys.append(poly)
return polys
Although this code works, it’s also a rather messy mix of small reads, struct unpacking,
and other details. If code like this is used to process a real datafile, it can quickly become
even messier. Thus, it’s an obvious candidate for an alternative solution that might sim‐
plify some of the steps and free the programmer to focus on more important matters.
In the remainder of this recipe, a rather advanced solution for interpreting binary data
will be built up in pieces. The goal will be to allow a programmer to provide a high-level
specification of the file format, and to simply have the details of reading and unpacking
all of the data worked out under the covers. As a forewarning, the code that follows may
be the most advanced example in this entire book, utilizing various object-oriented
programming and metaprogramming techniques. Be sure to carefully read the discus‐
sion section as well as cross-references to other recipes.
First, when reading binary data, it is common for the file to contain headers and other
data structures. Although the struct module can unpack this data into a tuple, another
way to represent such information is through the use of a class. Here’s some code that
allows just that:
6.12. Reading Nested and Variable-Sized Binary Structures  |  205
C# WinForms Viewer: Load, View, Convert, Annotate and Edit PDF
PDF Conversion. • Convert PDF to Microsoft Office Word (.docx). Draw PDF markups. PDF Protection. • Sign PDF document with signature. • Erase PDF text.
create pdf signature box; add jpg signature to pdf
C# WinForms Viewer: Load, View, Convert, Annotate and Edit Word
XDoc.HTML5 Viewer. XDoc.Windows Viewer. XDoc.Converter. View & Process. Word Conversion. • Convert Microsoft Office Word to PDF (.pdf). View Word outlines.
click to sign pdf; add jpeg signature to pdf
import struct
class StructField:
'''
Descriptor representing a simple structure field
'''
def __init__(selfformat, offset):
self.format = format
self.offset = offset
def __get__(self, instance, cls):
if instance is None:
return self
else:
r =  struct.unpack_from(self.format,
instance._bufferself.offset)
return r[0] if len(r) == 1 else r
class Structure:
def __init__(selfbytedata):
self._buffer = memoryview(bytedata)
This code uses a descriptor to represent each structure field. Each descriptor contains
struct-compatible format code along with a byte offset into an underlying memory
buffer. In the __get__() method, the struct.unpack_from() function is used to unpack
a value from the buffer without having to make extra slices or copies.
The Structure class just serves as a base class that accepts some byte data and stores it
as the underlying memory buffer used by the StructField descriptor. The use of a 
memoryview() in this class serves a purpose that will become clear later.
Using this code, you can now define a structure as a high-level class that mirrors the
information found in the tables that described the expected file format. For example:
class PolyHeader(Structure):
file_code = StructField('<i'0)
min_x = StructField('<d'4)
min_y = StructField('<d'12)
max_x = StructField('<d'20)
max_y = StructField('<d'28)
num_polys = StructField('<i'36)
Here is an example of using this class to read the header from the polygon data written
earlier:
>>> f = open('polys.bin''rb')
>>> phead = PolyHeader(f.read(40))
>>> phead.file_code == 0x1234
True
>>> phead.min_x
0.5
>>> phead.min_y
0.5
206  |  Chapter 6: Data Encoding and Processing
C# HTML5 Viewer: Load, View, Convert, Annotate and Edit Word
users can convert Convert Microsoft Office Word to searchable PDF online, create To view, convert, edit, process, built, sign Word documents, please refer to
create a pdf signature file; adding a signature to a pdf document
C# HTML5 Viewer: Load, View, Convert, Annotate and Edit PDF
as convert PDF to Microsoft Office Word (.docx) online C# users can view PDF outlines online To view, convert, edit, process, protect, sign PDF files, please
pdf will signature; create signature field in pdf
>>> phead.max_x
7.0
>>> phead.max_y
9.2
>>> phead.num_polys
3
>>>
This is interesting, but there are a number of annoyances with this approach. For one,
even though you get the convenience of a class-like interface, the code is rather verbose
and requires the user to specify a lot of low-level detail (e.g., repeated uses of Struct
Field, specification of offsets, etc.). The resulting class is also missing common con‐
veniences such as providing a way to compute the total size of the structure.
Any time you are faced with class definitions that are overly verbose like this, you might
consider the use of a class decorator or metaclass. One of the features of a metaclass is
that it can be used to fill in a lot of low-level implementation details, taking that burden
off of the user. As an example, consider this metaclass and slight reformulation of the
Structure class:
class StructureMeta(type):
'''
Metaclass that automatically creates StructField descriptors
'''
def __init__(selfclsnamebasesclsdict):
fields = getattr(self, '_fields_', [])
byte_order = ''
offset = 0
for formatfieldname in fields:
if format.startswith(('<','>','!','@')):
byte_order = format[0]
format = format[1:]
format = byte_order + format
setattr(selffieldname, StructField(format, offset))
offset += struct.calcsize(format)
setattr(self'struct_size'offset)
class Structure(metaclass=StructureMeta):
def __init__(selfbytedata):
self._buffer = bytedata
@classmethod
def from_file(clsf):
return cls(f.read(cls.struct_size))
Using this new Structure class, you can now write a structure definition like this:
class PolyHeader(Structure):
_fields_ = [
('<i''file_code'),
('d''min_x'),
('d''min_y'),
6.12. Reading Nested and Variable-Sized Binary Structures  |  207
XDoc.HTML5 Viewer for .NET, Zero Footprint AJAX Document Image
View, Convert, Edit, Sign Documents and Images. We are dedicated to provide powerful & profession imaging controls, PDF document, image to pdf files and
add signature field to pdf; adding signature to pdf file
XDoc.HTML5 Viewer for .NET, Technical Specifications Introductions
All Formats. XDoc.HTML5 Viewer. XDoc.Windows Viewer. XDoc.Converter. View & Process. XDoc.PDF. Scanning. Microsoft Office. XDoc.Word. XDoc.Excel. XDoc.PowerPoint.
add signature to pdf acrobat; add signature to preview pdf
('d''max_x'),
('d''max_y'),
('i''num_polys')
]
As you can see, the specification is a lot less verbose. The added from_file() class
method also makes it easier to read the data from a file without knowing any details
about the size or structure of the data. For example:
>>> f = open('polys.bin''rb')
>>> phead = PolyHeader.from_file(f)
>>> phead.file_code == 0x1234
True
>>> phead.min_x
0.5
>>> phead.min_y
0.5
>>> phead.max_x
7.0
>>> phead.max_y
9.2
>>> phead.num_polys
3
>>>
Once you introduce a metaclass into the mix, you can build more intelligence into it.
For example, suppose you want to support nested binary structures. Here’s a reformu‐
lation of the metaclass along with a new supporting descriptor that allows it:
class NestedStruct:
'''
Descriptor representing a nested structure
'''
def __init__(selfnamestruct_typeoffset):
self.name = name
self.struct_type = struct_type
self.offset = offset
def __get__(self, instance, cls):
if instance is None:
return self
else:
data = instance._buffer[self.offset:
self.offset+self.struct_type.struct_size]
result = self.struct_type(data)
# Save resulting structure back on instance to avoid
# further recomputation of this step
setattr(instanceself.nameresult)
return result
class StructureMeta(type):
'''
Metaclass that automatically creates StructField descriptors
208  |  Chapter 6: Data Encoding and Processing
XDoc.HTML5 Viewer for .NET Purchase information
All Formats. XDoc.HTML5 Viewer. XDoc.Windows Viewer. XDoc.Converter. View & Process. XDoc.PDF. Scanning. Microsoft Office. XDoc.Word. XDoc.Excel. XDoc.PowerPoint.
add signature pdf online; add signature box to pdf
XDoc.HTML5 Viewer for .NET, All Mature Features Introductions
View, Convert, Edit, Sign Documents and Images. Microsoft Word: DOC, DOCX, DOCM, DOT, DOTX, DOTM; PowerPoint: PPT, PPTX, PPS, PPSX; PDF: Portable Document Format;
create signature pdf; copy and paste signature into pdf
'''
def __init__(selfclsnamebasesclsdict):
fields = getattr(self, '_fields_', [])
byte_order = ''
offset = 0
for formatfieldname in fields:
if isinstance(format, StructureMeta):
setattr(selffieldname,
NestedStruct(fieldnameformatoffset))
offset += format.struct_size
else:
if format.startswith(('<','>','!','@')):
byte_order = format[0]
format = format[1:]
format = byte_order + format
setattr(selffieldnameStructField(format, offset))
offset += struct.calcsize(format)
setattr(self'struct_size'offset)
In this code, the NestedStruct descriptor is used to overlay another structure definition
over a region of memory. It does this by taking a slice of the original memory buffer
and using it to instantiate the given structure type. Since the underlying memory buffer
was initialized as a memoryview, this slicing does not incur any extra memory copies.
Instead, it’s just an overlay on the original memory. Moreover, to avoid repeated in‐
stantiations, the descriptor then stores the resulting inner structure object on the in‐
stance using the same technique described in Recipe 8.10.
Using this new formulation, you can start to write code like this:
class Point(Structure):
_fields_ = [
('<d''x'),
('d''y')
]
class PolyHeader(Structure):
_fields_ = [
('<i''file_code'),
(Point'min'),         # nested struct
(Point'max'),         # nested struct
('i''num_polys')
]
Amazingly, it will all still work as you expect. For example:
>>> f = open('polys.bin''rb')
>>> phead = PolyHeader.from_file(f)
>>> phead.file_code == 0x1234
True
>>> phead.min       # Nested structure
<__main__.Point object at 0x1006a48d0>
>>> phead.min.x
6.12. Reading Nested and Variable-Sized Binary Structures  |  209
0.5
>>> phead.min.y
0.5
>>> phead.max.x
7.0
>>> phead.max.y
9.2
>>> phead.num_polys
3
>>>
At this point, a framework for dealing with fixed-sized records has been developed, but
what about the variable-sized components? For example, the remainder of the polygon
files contain sections of variable size.
One way to handle this is to write a class that simply represents a chunk of binary data
along with a utility function for interpreting the contents in different ways. This is closely
related to the code in Recipe 6.11:
class SizedRecord:
def __init__(selfbytedata):
self._buffer = memoryview(bytedata)
@classmethod
def from_file(clsfsize_fmtincludes_size=True):
sz_nbytes = struct.calcsize(size_fmt)
sz_bytes = f.read(sz_nbytes)
sz= struct.unpack(size_fmtsz_bytes)
buf = f.read(sz - includes_size * sz_nbytes)
return cls(buf)
def iter_as(self, code):
if isinstance(code, str):
s = struct.Struct(code)
for off in range(0len(self._buffer), s.size):
yield s.unpack_from(self._buffer, off)
elif isinstance(code, StructureMeta):
size = code.struct_size
for off in range(0len(self._buffer), size):
data = self._buffer[off:off+size]
yield code(data)
The SizedRecord.from_file() class method is a utility for reading a size-prefixed
chunk of data from a file, which is common in many file formats. As input, it accepts a
structure format code containing the encoding of the size, which is expected to be in
bytes. The optional includes_size argument specifies whether the number of bytes
includes the size header or not. Here’s an example of how you would use this code to
read the individual polygons in the polygon file:
210  |  Chapter 6: Data Encoding and Processing
>>> f = open('polys.bin''rb')
>>> phead = PolyHeader.from_file(f)
>>> phead.num_polys
3
>>> polydata = [ SizedRecord.from_file(f'<i')
...              for n in range(phead.num_polys) ]
>>> polydata
[<__main__.SizedRecord object at 0x1006a4d50>,
<__main__.SizedRecord object at 0x1006a4f50>,
<__main__.SizedRecord object at 0x10070da90>]
>>>
As shown, the contents of the SizedRecord instances have not yet been interpreted. To
do that, use the iter_as() method, which accepts a structure format code or Struc
ture class as input. This gives you a lot of flexibility in how to interpret the data. For
example:
>>> for npoly in enumerate(polydata):
...     print('Polygon'n)
...     for p in poly.iter_as('<dd'):
...             print(p)
...
Polygon 0
(1.0, 2.5)
(3.5, 4.0)
(2.5, 1.5)
Polygon 1
(7.0, 1.2)
(5.1, 3.0)
(0.5, 7.5)
(0.8, 9.0)
Polygon 2
(3.4, 6.3)
(1.2, 0.5)
(4.6, 9.2)
>>>
>>> for npoly in enumerate(polydata):
...     print('Polygon'n)
...     for p in poly.iter_as(Point):
...             print(p.xp.y)
...
Polygon 0
1.0 2.5
3.5 4.0
2.5 1.5
Polygon 1
7.0 1.2
5.1 3.0
0.5 7.5
0.8 9.0
Polygon 2
6.12. Reading Nested and Variable-Sized Binary Structures  |  211
3.4 6.3
1.2 0.5
4.6 9.2
>>>
Putting all of this together, here’s an alternative formulation of the read_polys() func‐
tion:
class Point(Structure):
_fields_ = [
('<d''x'),
('d''y')
]
class PolyHeader(Structure):
_fields_ = [
('<i''file_code'),
(Point'min'),
(Point'max'),
('i''num_polys')
]
def read_polys(filename):
polys = []
with open(filename'rb'as f:
phead = PolyHeader.from_file(f)
for n in range(phead.num_polys):
rec = SizedRecord.from_file(f, '<i')
poly = [ (p.xp.y)
for p in rec.iter_as(Point) ]
polys.append(poly)
return polys
Discussion
This recipe provides a practical application of various advanced programming techni‐
ques, including descriptors, lazy evaluation, metaclasses, class variables, and memory‐
views. However, they all serve a very specific purpose.
A major feature of the implementation is that it is strongly based on the idea of lazy-
unpacking. When an instance of Structure is created, the __init__() merely creates
a memoryview of the supplied byte data and does nothing else. Specifically, no unpack‐
ing or other structure-related operations take place at this time. One motivation for
taking this approach is that you might only be interested in a few specific parts of a
binary record. Rather than unpacking the whole file, only the parts that are actually
accessed will be unpacked.
To implement the lazy unpacking and packing of values, the StructField descriptor
class is  used. Each attribute the user  lists  in _fields_ gets  converted  to a Struct
Field descriptor that stores the associated structure format code and byte offset into
212  |  Chapter 6: Data Encoding and Processing
Documents you may be interested
Documents you may be interested