run_code() submits a Python cell to the capsule’s persistent Jupyter kernel and returns once execution completes. The return value is an Execution object that contains all output the cell produced — expression values, printed text, and any exception that was raised.
The Execution object
run_code(code) returns an Execution instance with the following fields:
| Field | Type | Description |
|---|
results | list[Result] | Rich outputs from the cell — charts, images, expression values. |
logs | Logs | Captured stream output. .stdout: list[str] and .stderr: list[str]. |
error | ExecutionError | None | Populated when the cell raised an exception. |
execution_count | int | None | Jupyter cell execution counter ([N] in a notebook). |
text (property) | str | None | text/plain of the main execute_result — the last expression’s value. |
result.logs.stdout and result.logs.stderr are lists of string chunks, one per kernel stream message. Join them with "".join(result.logs.stdout) to get the full output.
Error handling
When code raises an exception, run_code() does not raise a Python exception in your calling code. Instead, it populates result.error with an ExecutionError object.
from wrenn.code_interpreter import Capsule
with Capsule(wait=True) as capsule:
result = capsule.run_code("1 / 0")
if result.error:
print(result.error.name) # "ZeroDivisionError"
print(result.error.value) # "division by zero"
print(result.error.traceback) # full traceback string
The ExecutionError fields are:
| Field | Type | Description |
|---|
name | str | Exception class name, e.g. "ZeroDivisionError". |
value | str | Exception message. |
traceback | str | Full traceback as a single string. |
Errors in the executed code populate result.error — they do not raise exceptions in your calling code. Always check result.error when you need to handle failures.
Streaming callbacks
If you want to receive output as it arrives rather than waiting for the cell to finish, pass callback functions to run_code().
with Capsule(wait=True) as capsule:
capsule.run_code(
"""
import time
for i in range(5):
print(f"step {i}")
time.sleep(0.5)
""",
on_stdout=lambda text: print("stdout:", text, end=""),
on_stderr=lambda text: print("stderr:", text, end=""),
on_result=lambda r: print("result:", r.formats()),
on_error=lambda err: print(f"error: {err.name}: {err.value}"),
)
The available callbacks are:
| Parameter | Called when |
|---|
on_result | A rich output is produced (execute_result or display_data). |
on_stdout | A stdout chunk arrives from the kernel. |
on_stderr | A stderr chunk arrives from the kernel. |
on_error | The cell raises an exception. |
run_code() still returns the complete Execution object after the cell finishes, even when you use callbacks. The callbacks and the return value contain the same data.