Claude Code for code: Python Interactive Interpreter Utilities — Claude Skills 360 Blog
Blog / AI / Claude Code for code: Python Interactive Interpreter Utilities
AI

Claude Code for code: Python Interactive Interpreter Utilities

Published: December 25, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s code module supplies the classes behind python -i — interactive console and interpreter utilities for embedding a REPL in your application. import code. Quick REPL: code.interact(banner=None, local=None, exitmsg=None) — starts a read-eval-print loop in the current process; local dict becomes the interpreter namespace. Console class: c = code.InteractiveConsole(locals=None) — manages a read-eval-print session; c.push(line)bool (True = more input needed); c.runsource(source, filename="<input>", symbol="single") — compile + run a source string; c.resetbuffer() — clear accumulated input. Interpreter class: i = code.InteractiveInterpreter(locals=None) — lower level; i.runsource(source), i.runcode(code_obj), i.showsyntaxerror(filename=None), i.showtraceback(). Compile check: code.compile_command(source, filename="<input>", symbol="single") → compiled code (complete), None (incomplete), raises SyntaxError (bad). Add tab completion: import readline, rlcompleter; readline.parse_and_bind("tab: complete") before calling interact. Claude Code generates embedded REPLs, in-process sandboxes, notebook kernels, and debug console helpers.

CLAUDE.md for code

## code Stack
- Stdlib: import code, readline, rlcompleter
- Quick:  code.interact(local={"db": conn})  # drop into REPL
- Console: c = code.InteractiveConsole(locals={"x": 42})
-          c.interact(banner="Custom REPL")
- Push:   more = c.push("def f(x):")   # True = needs more
-         more = c.push("    return x") # still True
-         more = c.push("")             # False = executed
- Note:   runsource returns False when source is complete

code Interactive Console Pipeline

# app/codeutil.py — console, sandbox, capture, completion, kernel
from __future__ import annotations

import code
import io
import sys
import traceback
from contextlib import contextmanager, redirect_stdout, redirect_stderr
from dataclasses import dataclass, field
from typing import Any


# ─────────────────────────────────────────────────────────────────────────────
# 1. Basic console helpers
# ─────────────────────────────────────────────────────────────────────────────

def start_repl(
    local: "dict[str, Any] | None" = None,
    banner: str = "Python REPL  (Ctrl-D to exit)",
    exitmsg: str = "",
    with_completion: bool = True,
) -> None:
    """
    Start an interactive REPL with optional tab completion.

    Example:
        from myapp import db, User
        start_repl(local={"db": db, "User": User}, banner="App Shell")
    """
    namespace = dict(local or {})

    if with_completion:
        try:
            import readline
            import rlcompleter
            readline.set_completer(rlcompleter.Completer(namespace).complete)
            readline.parse_and_bind("tab: complete")
        except ImportError:
            pass

    code.interact(banner=banner, local=namespace, exitmsg=exitmsg)


def compile_check(source: str) -> "str":
    """
    Check whether source is complete, incomplete, or invalid.
    Returns 'complete', 'incomplete', or 'invalid'.

    Example:
        print(compile_check("x = 1 + 2"))   # "complete"
        print(compile_check("def f():"))     # "incomplete"
        print(compile_check("x = 1 +"))     # "invalid"
    """
    try:
        result = code.compile_command(source)
        return "complete" if result is not None else "incomplete"
    except SyntaxError:
        return "invalid"


# ─────────────────────────────────────────────────────────────────────────────
# 2. Capturing interpreter output
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class ExecResult:
    """
    Result of running source in a captured interpreter.

    Example:
        result = exec_source("x = 1 + 2\nprint(x)")
        print(result.stdout)   # "3\n"
        print(result.ok)       # True
    """
    stdout:   str
    stderr:   str
    ok:       bool
    error:    str
    more:     bool  # True if source ended with an incomplete statement

    def __str__(self) -> str:
        status = "OK" if self.ok else f"ERROR({self.error[:60]})"
        return f"ExecResult({status}  stdout={self.stdout!r}  stderr={self.stderr!r})"


def exec_source(
    source: str,
    namespace: "dict[str, Any] | None" = None,
) -> ExecResult:
    """
    Execute Python source in an isolated namespace, capturing stdout/stderr.

    Example:
        r = exec_source("import math\nprint(math.pi)")
        print(r.stdout)   # "3.141592653589793\n"
    """
    ns = dict(namespace or {})
    stdout_buf = io.StringIO()
    stderr_buf = io.StringIO()
    interp = code.InteractiveInterpreter(locals=ns)

    class Capture(code.InteractiveInterpreter):
        def write(self, data: str) -> None:
            stderr_buf.write(data)

    cap = Capture(locals=ns)

    # Redirect stdout for print() output
    old_out, old_err = sys.stdout, sys.stderr
    sys.stdout = stdout_buf
    sys.stderr = stderr_buf
    try:
        more = cap.runsource(source, filename="<exec>", symbol="exec")
    finally:
        sys.stdout = old_out
        sys.stderr = old_err

    out = stdout_buf.getvalue()
    err = stderr_buf.getvalue()
    return ExecResult(
        stdout=out,
        stderr=err,
        ok=not err,
        error=err.strip(),
        more=more,
    )


# ─────────────────────────────────────────────────────────────────────────────
# 3. Sandboxed console
# ─────────────────────────────────────────────────────────────────────────────

class SandboxConsole:
    """
    An in-process sandboxed console that captures output per-execution.
    Maintains state across pushes (like a real REPL session).

    Example:
        sb = SandboxConsole({"x": 10})
        r1 = sb.push("y = x * 2")
        r2 = sb.push("print(y)")
        print(r2.stdout)   # "20\n"
    """

    def __init__(self, initial_locals: "dict[str, Any] | None" = None) -> None:
        self.namespace: dict[str, Any] = dict(initial_locals or {})
        self._console = code.InteractiveConsole(locals=self.namespace)
        self._buffer: list[str] = []

    def push(self, line: str) -> ExecResult:
        """
        Feed one line to the console. Returns ExecResult with captured output.
        """
        stdout_buf = io.StringIO()
        stderr_buf = io.StringIO()
        old_out, old_err = sys.stdout, sys.stderr
        sys.stdout = stdout_buf
        sys.stderr = stderr_buf
        try:
            more = self._console.push(line)
        finally:
            sys.stdout = old_out
            sys.stderr = old_err

        out = stdout_buf.getvalue()
        err = stderr_buf.getvalue()
        return ExecResult(
            stdout=out,
            stderr=err,
            ok=not err,
            error=err.strip(),
            more=more,
        )

    def run_block(self, source: str) -> list[ExecResult]:
        """
        Push each line of a multi-line source block, return all results.

        Example:
            results = sb.run_block("for i in range(3):\\n    print(i)")
        """
        results = []
        for line in source.splitlines():
            results.append(self.push(line))
        # Flush any pending compound statement
        results.append(self.push(""))
        return results

    def reset(self) -> None:
        """Reset the input buffer (for incomplete statements)."""
        self._console.resetbuffer()

    def get_namespace(self) -> dict[str, Any]:
        """Return a snapshot of the current interpreter namespace."""
        return dict(self.namespace)


# ─────────────────────────────────────────────────────────────────────────────
# 4. Multi-line input accumulator
# ─────────────────────────────────────────────────────────────────────────────

class MultiLineBuffer:
    """
    Accumulate lines from a text stream until a complete Python statement
    is ready, then hand it off for execution.

    Example:
        buf = MultiLineBuffer()
        buf.feed("def add(a, b):")         # → more=True
        buf.feed("    return a + b")       # → more=True
        buf.feed("")                       # → more=False, source ready
        if buf.ready:
            print(buf.source)
    """

    def __init__(self) -> None:
        self._lines: list[str] = []
        self.ready = False
        self.source = ""

    def feed(self, line: str) -> bool:
        """
        Add a line. Returns True if more input is needed.
        When complete, sets self.ready=True and self.source.
        """
        self._lines.append(line)
        joined = "\n".join(self._lines)
        try:
            result = code.compile_command(joined)
        except SyntaxError:
            self.ready = True
            self.source = joined
            self._lines.clear()
            return False

        if result is not None:
            self.ready = True
            self.source = joined
            self._lines.clear()
            return False
        return True

    def reset(self) -> None:
        """Clear pending lines without executing."""
        self._lines.clear()
        self.ready = False
        self.source = ""


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== code demo ===")

    # ── compile_check ─────────────────────────────────────────────────────────
    print("\n--- compile_check ---")
    for src in [
        "x = 1 + 2",
        "def f():",
        "if True:",
        "x = 1 +",
        "print('hello')",
    ]:
        print(f"  {src!r:30s}{compile_check(src)}")

    # ── exec_source ───────────────────────────────────────────────────────────
    print("\n--- exec_source ---")
    r = exec_source("import math\nprint(f'pi={math.pi:.4f}')")
    print(f"  {r}")

    r2 = exec_source("x = 1 +  # syntax error")
    print(f"  {r2}")

    # ── SandboxConsole ────────────────────────────────────────────────────────
    print("\n--- SandboxConsole ---")
    sb = SandboxConsole({"greeting": "Hello"})
    lines = [
        "name = 'World'",
        "print(f'{greeting}, {name}!')",
        "result = 6 * 7",
    ]
    for line in lines:
        r3 = sb.push(line)
        if r3.stdout:
            print(f"  output: {r3.stdout!r}")
    ns = sb.get_namespace()
    print(f"  result = {ns.get('result')}")

    # ── run_block ─────────────────────────────────────────────────────────────
    print("\n--- SandboxConsole.run_block ---")
    sb2 = SandboxConsole()
    block = "for i in range(3):\n    print(i)"
    results = sb2.run_block(block)
    all_stdout = "".join(r.stdout for r in results)
    print(f"  loop output: {all_stdout!r}")

    # ── MultiLineBuffer ────────────────────────────────────────────────────────
    print("\n--- MultiLineBuffer ---")
    buf = MultiLineBuffer()
    inputs = ["def square(x):", "    return x * x", ""]
    for line in inputs:
        more = buf.feed(line)
        print(f"  push({line!r})  more={more}  ready={buf.ready}")
    if buf.ready:
        print(f"  source: {buf.source!r}")

    print("\n=== done ===")

For the exec() built-in alternative — exec(compile(source, "<string>", "exec"), namespace) runs one code block with full namespace control — use exec for single-shot script execution where you have the complete source; use code.InteractiveConsole / code.InteractiveInterpreter when you need to support incremental line-by-line input with automatic multi-line statement detection (the push → more loop) and the standard sys.ps1/sys.ps2 prompt handling. For the IPython / ptpython (PyPI) alternative — these provide syntax highlighting, multi-line editing, magic commands, and rich output display — use IPython for data science and exploratory REPL sessions; use code.InteractiveConsole when embedding a minimal, zero-dependency REPL inside an application (CLI tools, debugger prompts, admin shells). The Claude Skills 360 bundle includes code skill sets covering start_repl() with tab completion setup, compile_check() → complete/incomplete/invalid, ExecResult dataclass, exec_source() captured stdout/stderr, SandboxConsole with push()/run_block()/get_namespace() stateful session, and MultiLineBuffer incremental input accumulator with feed()/reset(). Start with the free tier to try interactive REPL patterns and code module pipeline code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free