packed is a Python library that provides a simple way to serialize (pack) and deserialize (unpack) custom Python objects, leveraging the efficient MessagePack binary serialization format. It's designed to help you easily transmit objects over networks, save them to files, or perform any operation that requires converting objects to bytes and back.
- Efficient Binary Serialization: Uses MessagePack, an efficient binary serialization format that's faster and smaller than JSON.
- Simple Decorator-Based Registration: Easily register your custom classes for packing and unpacking using the
@packable
decorator. - Customizable Serialization: Define exactly what data gets serialized by implementing the
__packed__
method. - Supports Custom Unpacking Logic: Use the
__unpacked__
class method to control how objects are reconstructed during unpacking. - Seamless Integration: Works with standard Python types and custom objects, making it easy to integrate into existing projects.
Install packed using pip
:
pip3 install packed
To make a custom class packable, decorate it with @packable
and define a __packed__
method that returns a dictionary of the attributes you want to serialize.
from packed import packable
@packable # Register the class for packing
class EqualMatcher:
def __init__(self, expected):
self._expected = expected
def match(self, actual):
return actual == self._expected
def __packed__(self): # Select the fields to pack
return {"expected": self._expected}
Use the pack
function to serialize an object into bytes.
Client Side:
from packed import pack
matcher = EqualMatcher("banana")
packed_data = pack(matcher)
# You can now send 'packed_data' over a network or save it to a file
Use the unpack
function to deserialize bytes back into an object.
Server Side:
from packed import unpack
# Assume 'packed_data' is received from a network or read from a file
matcher = unpack(packed_data)
assert matcher.match("banana") is True
packed supports serialization of the following standard Python data types:
- Primitive Types:
int
,float
,bool
,None
,str
,bytes
- Collections:
- Lists:
[1, 2, 3]
- Tuples:
(1, 2, 3)
- Dictionaries:
{'key': 'value'}
- Sets:
{1, 2, 3}
- Lists:
- Nested Structures: Collections containing other collections or primitive types.
- Custom Objects: Classes registered with the
@packable
decorator.
These types are serialized using MessagePack's built-in support for these data types, ensuring efficient and reliable serialization.
-
Registration: When you decorate a class with
@packable
, it gets registered with the internal resolver. This allows thepacked
library to keep track of which classes can be packed and unpacked. -
Packing:
- The
__packed__
method you define in your class specifies what data gets serialized. - The
pack
function uses this method to convert your object into a serializable form. - Metadata about the object's class is included to ensure it can be properly reconstructed.
- The
-
Unpacking:
- The
unpack
function reads the metadata and reconstructs the object. - If your class defines a
__unpacked__
class method, it will use that to create the object. - Otherwise, it will call the class constructor with the unpacked data.
- The
If your class requires custom logic during unpacking, define a __unpacked__
class method.
@packable
class MyClass:
def __init__(self, value):
self.value = value
def __packed__(self):
return {'value': self.value}
@classmethod
def __unpacked__(cls, value):
# Custom logic during unpacking
instance = cls(value)
instance.setup_additional_state()
return instance
def setup_additional_state(self):
# Additional initialization
pass
You can register a class with a custom name by passing the name to the decorator. This is useful if you need to avoid name collisions or want to use a different identifier.
@packable("CustomName")
class MyClass:
# Class definition
If you have a class hierarchy, register each subclass separately if you intend to pack and unpack them.
@packable
class BaseClass:
# Base class definition
@packable
class SubClass(BaseClass):
# Subclass definition
MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON but it's faster and smaller.
By using MessagePack under the hood, packed provides:
- Efficiency: Smaller message sizes and faster serialization/deserialization compared to text-based formats like JSON.
- Interoperability: Support for multiple languages, making it easier to integrate with systems written in different programming languages.
- Simplicity: A straightforward and easy-to-use API.
packed uses umsgpack, a pure Python implementation of MessagePack, for serialization and deserialization. This ensures that the library is lightweight and has minimal dependencies, making it easy to install and integrate.