This guide covers resource management and cleanup strategies for sandboxes. Reliable cleanup prevents orphaned sandboxes after a script exits, which keeps costs predictable and avoids unintentional compute resource usage. The patterns here apply to scripts that create one or many sandboxes, with or without an explicit session.
Automatic cleanup
Automatic cleanup ties a sandbox’s lifetime to a Python construct (a context manager or the running process) so the SDK releases resources without explicit stop() calls.
Context managers (recommended)
Context managers are the recommended pattern because they guarantee cleanup even if the enclosed code raises an exception. The SDK stops sandboxes when the context exits:
from cwsandbox import Sandbox
with Sandbox.run() as sandbox:
result = sandbox.exec(["echo", "hello"]).result()
# sandbox.stop() called automatically
Sessions clean up all their sandboxes:
import cwsandbox
from cwsandbox import SandboxDefaults
with cwsandbox.Session(SandboxDefaults(container_image="python:3.11")) as session:
sb1 = session.sandbox()
sb2 = session.sandbox()
# Both sandboxes stopped automatically
Global cleanup handlers
For cases where a context manager isn’t practical, the SDK registers cleanup handlers that run when the process terminates:
| Scenario | Behavior |
|---|
| Normal script exit | atexit handler stops all sandboxes |
Ctrl+C (SIGINT) | Signal handler stops all sandboxes |
SIGTERM | Signal handler stops all sandboxes |
| Second Ctrl+C | Force exit (prevents unresponsive shutdown) |
Manual cleanup
Use manual cleanup when you need explicit control over when to release a sandbox or session. Manual cleanup lets you pass stop options or coordinate cleanup across long-running code.
Sandbox stop()
sandbox = Sandbox.run()
result = sandbox.exec(["echo", "hello"]).result()
sandbox.stop().result()
# With options
sandbox.stop(graceful_shutdown_seconds=30.0).result()
sandbox.stop(snapshot_on_stop=True).result()
Session close()
from cwsandbox import SandboxDefaults
session = cwsandbox.Session(SandboxDefaults(container_image="python:3.11"))
sandbox = session.sandbox()
# ...
session.close().result() # Stops all sandboxes
Batch cleanup
from cwsandbox import results
sandboxes = [Sandbox.run() for _ in range(5)]
# ... use sandboxes ...
results([sb.stop() for sb in sandboxes]) # Stop all in parallel
Orphan management
Orphans are sandboxes that outlive the process that created them. The following sections describe how to make orphans easy to find, how to query for them, and how to bring them back under managed cleanup.
Tagging for discovery
The SDK’s automatic cleanup handlers prevent most orphans. Sandboxes can keep running after forced shutdowns (kill -9), network failures, or when you create sandboxes outside of sessions and context managers. Use tags to make any orphans discoverable later.
from cwsandbox import Sandbox, SandboxDefaults
# Tag at creation time
defaults = SandboxDefaults(
container_image="python:3.11",
tags=("my-project", "batch-job-123"),
)
with Sandbox.run(defaults=defaults) as sandbox:
result = sandbox.exec(["echo", "hello"]).result()
Good tagging practices:
- Project or application name (
my-project)
- Job or run identifier (
batch-job-123, run-2024-01-15)
- Environment (
dev, staging, prod)
Find orphaned sandboxes
Query by tags to find sandboxes from previous runs:
from cwsandbox import Sandbox
orphans = Sandbox.list(tags=["my-project"]).result()
for sandbox in orphans:
sandbox.stop().result()
Session adoption
Adopting an orphan attaches it to a session so the session governs its lifetime. The orphan then receives the same automatic cleanup guarantees as newly created sandboxes:
import cwsandbox
from cwsandbox import SandboxDefaults
with cwsandbox.Session(SandboxDefaults(container_image="python:3.11")) as session:
orphans = session.list(tags=["my-project"]).result()
for sandbox in orphans:
session.adopt(sandbox)
# All adopted sandboxes cleaned up with session
Delete by ID
When you already know a sandbox’s ID, you can delete it directly without listing or adopting it first:
from cwsandbox import Sandbox
Sandbox.delete("sandbox-abc123").result()
Sandbox.delete("sandbox-abc123", missing_ok=True) # Ignore if gone
Last modified on May 29, 2026