Loro Python Bindings
Loro provides high-performance Python bindings for the Loro Conflict-free Replicated Data Type (CRDT) library. It enables real-time collaboration and local-first software development by offering conflict-free data synchronization across distributed environments. The library supports various rich data types like Text, List, Map, and Tree. Currently at version 1.10.3, it maintains an active development and release schedule.
Warnings
- breaking The `Loro` class was renamed to `LoroDoc` in Loro v1.0. Code using `Loro()` as the entry point will break.
- breaking Loro v1.9.0 and later removed legacy v0.x encoding support. Documents created with v0.x must be migrated via an intermediate Loro release (version <=1.8.x) before upgrading to v1.9.0 or newer.
- gotcha When defining Python functions that might interact with Loro's mutable data structures (e.g., passing a `LoroList` as a default argument to be modified), avoid using mutable objects as default argument values. This can lead to unexpected state sharing across function calls.
Install
-
pip install loro
Imports
- LoroDoc
from loro import LoroDoc
Quickstart
from loro import LoroDoc
# Create a new document
doc = LoroDoc()
# Get a text container (creates it if it doesn't exist)
text = doc.get_text("my-shared-text")
# Insert text at a specific position
text.insert(0, "Hello, Loro!")
# You can also use other CRDT types like Map or List
map_container = doc.get_map("my-shared-map")
map_container["key"] = "value"
# To observe changes, subscribe to the document
def on_change(event):
print(f"Document changed: {event}")
# Store the subscription reference to prevent garbage collection if running in an interactive session
sub = doc.subscribe_root(on_change)
# Commit changes to generate an update (important for sharing/persisting)
doc.commit()
# To get the current state as a snapshot
snapshot = doc.export(mode="snapshot")
print(f"Snapshot size: {len(snapshot)} bytes")
# To load a document from a snapshot
new_doc = LoroDoc()
new_doc.import_from(snapshot)
print(f"Loaded text: {new_doc.get_text('my-shared-text').get_value()}")