Skip to main content

User Guide 📚

Master Crous with comprehensive tutorials, practical examples, and best practices.

🚀 Getting Started

Your First Program

Let's get you up and running with your first Crous script:

import crous

# Create some data
data = {
'name': 'Alice',
'age': 30,
'tags': ['python', 'developer']
}

# Serialize to bytes
binary = crous.dumps(data)
print(f"✓ Serialized {len(binary)} bytes")

# Deserialize back
result = crous.loads(binary)
print(f"✓ Deserialized: {result}")
assert result == data
Installation

If you haven't installed Crous yet, check the Installation Guide.

📦 Basic Serialization

Supported Types

Crous handles Python's fundamental types:

import crous

data = {
'none': None,
'bool_true': True,
'bool_false': False,
'integer': 42,
'float': 3.14,
'string': 'Hello, World!',
'bytes': b'binary data',
}

binary = crous.dumps(data)
result = crous.loads(binary)
assert result == data

Type Preservation ✨

Unlike JSON, Crous preserves Python types:

import crous
import json

data = {
'int_value': 1,
'float_value': 1.0,
'bool_value': True,
'bytes_value': b'data',
'tuple_value': (1, 2, 3),
}

# ✓ With Crous - Types are preserved!
crous_binary = crous.dumps(data)
crous_result = crous.loads(crous_binary)
assert type(crous_result['int_value']) is int # ✓
assert type(crous_result['float_value']) is float # ✓
assert type(crous_result['tuple_value']) is tuple # ✓

# ✗ With JSON - Some types are lost
json_str = json.dumps(data) # Oops! Tuples become lists, bytes not supported
Why This Matters

Type preservation is critical for applications where:

  • Configuration needs exact types (e.g., 1 vs 1.0)
  • Round-trip integrity is required
  • You're building type-safe systems

📁 File I/O

Working with Files

import crous

data = {'config': {'debug': True, 'port': 8080}}

# Save to file
crous.dump(data, 'config.crous')

# Load from file
config = crous.load('config.crous')
assert config == data

🔧 Custom Types

Why Custom Serializers?

By default, Crous handles basic Python types. For other types like datetime, Decimal, or your own classes, you need custom serializers:

Dictionary Keys Must Be Strings

Crous dictionaries only support string keys. If you need non-string keys, convert them to strings as part of your serializer.

from datetime import datetime
import crous

# Register a serializer
def serialize_datetime(obj):
if isinstance(obj, datetime):
return obj.isoformat() # Convert to ISO string
raise TypeError(f"Cannot serialize {type(obj)}")

crous.register_serializer(datetime, serialize_datetime)

# Now datetime works!
data = {
'created': datetime(2024, 1, 15, 10, 30),
'updated': datetime.now(),
}
binary = crous.dumps(data)
result = crous.loads(binary)
print(result['created']) # '2024-01-15T10:30:00'

❌ Error Handling

Exception Types

import crous

# ❌ Non-string dictionary keys
try:
crous.dumps({1: 'one', 2: 'two'})
except crous.CrousEncodeError as e:
print(f"Encoding error: {e}")

# ❌ Unsupported type
try:
crous.dumps({'obj': object()})
except crous.CrousEncodeError as e:
print(f"Cannot serialize: {e}")

⚡ Performance Tips

1. Batch Operations

import crous
import time

# ❌ Slow: Many small operations
items = [{'id': i, 'value': i*2} for i in range(10000)]
start = time.time()
for item in items:
crous.dumps(item)
slow_time = time.time() - start

# ✓ Fast: Serialize once
start = time.time()
binary = crous.dumps(items)
fast_time = time.time() - start

print(f"Slow: {slow_time:.3f}s, Fast: {fast_time:.3f}s")
print(f"Speedup: {slow_time/fast_time:.1f}x faster")

2. File I/O for Large Data

import crous

large_data = {
'records': [{'id': i, 'data': 'x' * 1000} for i in range(100000)]
}

# ✓ Better for large files
crous.dump(large_data, 'output.crous')

🎯 Advanced Usage

Custom Object Hook

Modify dictionaries during deserialization:

import crous

def uppercase_keys(d):
"""Convert all dict keys to uppercase."""
return {k.upper(): v for k, v in d.items()}

data = {'name': 'alice', 'age': 30}
binary = crous.dumps(data)

# Normal
normal = crous.loads(binary)
print(normal) # {'name': 'alice', 'age': 30}

# With hook
modified = crous.loads(binary, object_hook=uppercase_keys)
print(modified) # {'NAME': 'alice', 'AGE': 30}

Comparison with Other Formats

import json
import crous

data = {
'name': 'Alice',
'scores': [95.5, 87.3, 92.1],
'active': True,
}

# JSON: Text-based, human-readable
json_str = json.dumps(data)
json_bytes = json_str.encode('utf-8')
print(f"JSON: {len(json_bytes)} bytes")

# Crous: Binary, more compact
crous_bytes = crous.dumps(data)
print(f"Crous: {len(crous_bytes)} bytes")
print(f"Reduction: {(1 - len(crous_bytes)/len(json_bytes)) * 100:.1f}%")

Next Steps