Serpent Serialization Library
Serpent is a simple serialization library for Python based on `ast.literal_eval`. It serializes object trees into a safe, human-readable, UTF-8 encoded string (a valid Python literal expression), suitable for data interchange between Python, Java, and .NET. As of version 1.42, it actively maintains support for modern Python versions with a release cadence of a few months to a year.
Warnings
- gotcha Although based on `ast.literal_eval` (which is safer than `eval()`), processing untrusted input with Serpent can still lead to Denial of Service (DoS) attacks, such as memory exhaustion or C stack exhaustion, by crafting malicious inputs.
- gotcha When serializing `bytes`, `bytearray`, or `memoryview` objects, Serpent defaults to base-64 encoding. To retrieve the original `bytes` object during deserialization, you must manually decode the string using `serpent.tobytes()`. Alternatively, using the `bytes_repr=True` option during serialization (available since 1.40) will output Python's `bytes` literal representation, but this generally results in larger and slower serialization.
- gotcha Serpent cannot serialize object graphs with circular references (where an object refers to itself, directly or indirectly). Attempting to do so will result in a `ValueError`.
- breaking Support for Python 3.11 introduced changes to `__getstate__` behavior. Serpent versions prior to 1.41 may fail to correctly serialize custom objects implementing `__getstate__` when running on Python 3.11 or newer.
- gotcha The serializer instance itself is not thread-safe. Avoid modifying the object tree being serialized while `dumps()` is running, and do not use the same `dumps()` (or a shared underlying serializer instance) across multiple threads concurrently.
Install
-
pip install serpent
Imports
- dumps
from serpent import dumps
- loads
from serpent import loads
- tobytes
from serpent import tobytes
Quickstart
from serpent import dumps, loads
data = {
'name': 'Serpent Example',
'version': 1.0,
'is_active': True,
'items': [1, 2, {'id': 'a'}]
}
# Serialize the data
serialized_bytes = dumps(data, indent=True) # indent=True for pretty-printing
print(f"Serialized data:\n{serialized_bytes.decode('utf-8')}")
# Deserialize the data
deserialized_data = loads(serialized_bytes)
print(f"Deserialized data: {deserialized_data}")
print(f"Is deserialized data equal to original? {data == deserialized_data}")