Skip to main content
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:
FieldTypeDescription
resultslist[Result]Rich outputs from the cell — charts, images, expression values.
logsLogsCaptured stream output. .stdout: list[str] and .stderr: list[str].
errorExecutionError | NonePopulated when the cell raised an exception.
execution_countint | NoneJupyter cell execution counter ([N] in a notebook).
text (property)str | Nonetext/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:
FieldTypeDescription
namestrException class name, e.g. "ZeroDivisionError".
valuestrException message.
tracebackstrFull 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:
ParameterCalled when
on_resultA rich output is produced (execute_result or display_data).
on_stdoutA stdout chunk arrives from the kernel.
on_stderrA stderr chunk arrives from the kernel.
on_errorThe 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.