Serialization

Most of the Serialization process uses Archives, which describe every recorded object before transforming them into a storable format.

The archive API serializes objects whose exact classes are known to the serialization registry. The standard Python container types and supported Perceval classes are registered when Perceval is imported. It is possible to add your own classes to the registry (see Registering new classes).

Serializing an object

Create an OutputArchive, then add an object with serialize():

>>> import perceval as pcvl
>>> from perceval.serialization import OutputArchive, Serialization
>>>
>>> circuit = pcvl.Circuit(2) // pcvl.BS.H()
>>> output_archive = OutputArchive()
>>> Serialization.serialize(circuit, output_archive)
>>> serialized_circuit = output_archive.to_text()

The returned string contains the archive format version, its root objects, and the registered type tags needed to reconstruct the objects. Treat this representation as an opaque string: use the archive API instead of parsing or editing it directly.

Set compress=True to produce a compressed text representation:

>>> compressed_circuit = output_archive.to_text(compress=True)

Both representations can be passed to from_text().

Deserializing an object

Build an InputArchive from the stored text, then retrieve the object with deserialize():

>>> from perceval.serialization import InputArchive
>>>
>>> input_archive = InputArchive.from_text(serialized_circuit)
>>> restored_circuit = Serialization.deserialize(input_archive)
>>> type(restored_circuit) is pcvl.Circuit
True
>>> restored_circuit.m
2

Note

The legacy perceval.serialization.deserialize() method is able to read from an archive string. In that case, it returns the first serialized object.

Serializing several objects

An archive can contain more than one root object. Call Serialization.serialize once for each object, then call Serialization.deserialize in the same order:

>>> state = pcvl.BasicState("|1,0>")
>>> output_archive = OutputArchive()
>>> Serialization.serialize(circuit, output_archive)
>>> Serialization.serialize(state, output_archive)
>>>
>>> input_archive = InputArchive.from_text(output_archive.to_text())
>>> restored_circuit = Serialization.deserialize(input_archive)
>>> restored_state = Serialization.deserialize(input_archive)

Deserializing consumes one root from the input archive. len(input_archive) returns the number of roots that have not yet been consumed.

Object identity

Objects are memoized inside an archive. When the same mutable object appears several times in the serialized object graph, every occurrence points to the same restored instance:

>>> shared = [1, 2]
>>> value = [shared, shared]
>>> output_archive = OutputArchive()
>>> Serialization.serialize(value, output_archive)
>>> restored = Serialization.deserialize(InputArchive.from_text(output_archive.to_text()))
>>> restored[0] is restored[1]
True

This memoization also allows registered serializers to handle cyclic object graphs.

API reference

class perceval.serialization.OutputArchive(raise_on_unregistred_class=True)

Archive used to serialize objects

save_attr(obj, attributes)

Adds all the given attributes of obj to the archive.

Parameters:
  • obj – The object that is currently being added to the archive

  • attributes (list[str]) – A list of attributes of the object that will be added to the archive

Return type:

tuple[ADescriptor, list[object]]

Returns:

A PartialRecord, i.e. a descriptor and a list of all new objects to add to the archive.

to_json()
Return type:

dict[str, Any]

Returns:

A dict representation of the archive, that can be converted to str using json.dumps

to_text(compress=False)
Parameters:

compress (bool) – If True, the resulting string will be compressed

Return type:

str

Returns:

A string representing all the data stored in the archive

class perceval.serialization.InputArchive(raise_on_unregistred_class=True)

Archive used to deserialize objects

create(index)
Parameters:

index (int) – The index of the object to create in the archive

Return type:

object

Returns:

The object that was created in the archive

classmethod from_json(json_obj)
Parameters:

json_obj (dict) – a dict representing an archive, typically obtained by using an OutputArchive.to_json() method.

Return type:

InputArchive

Returns:

A new InputArchive containing the data that were stored in the archive.

classmethod from_text(txt)
Parameters:

txt (str) – a string representing an archive, typically obtained by using an OutputArchive.to_txt() method.

Return type:

InputArchive

Returns:

A new InputArchive containing the data that were stored in the archive.

load_attr(obj, desc)

Creates and loads as attributes all the objects described in desc into obj. :type obj: :param obj: The object that will receive the attributes. :type desc: list[tuple[str, int]] :param desc: A list of pairs (attribute_name, index)

static Serialization.serialize(obj, ar)

Adds obj to the output archive, marking it as a root object

static Serialization.deserialize(ar)

Deserializes the next root object in the input archive, and returns it

Raises:

RuntimeError – if all the roots have been deserialized.