Claude Code for sys: Python Interpreter State and Control — Claude Skills 360 Blog
Blog / AI / Claude Code for sys: Python Interpreter State and Control
AI

Claude Code for sys: Python Interpreter State and Control

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

Python’s sys module exposes the interpreter’s runtime state. import sys. Arguments: sys.argvlist[str]argv[0] is the script name. Exit: sys.exit(code=0) — raises SystemExit(code); code=0 is success; non-zero is error; a string prints to stderr and exits 1. Streams: sys.stdin, sys.stdout, sys.stderr — file-like objects; reassign to redirect I/O. Path: sys.path — module search directories; sys.path.insert(0, dir) to prepend. Modules: sys.modules — cache dict {name: module}; del sys.modules["mod"] forces reimport. Version: sys.version_info(major, minor, micro, releaselevel, serial) named tuple; check: sys.version_info >= (3, 11). Platform: sys.platform"linux", "darwin", "win32". Executable: sys.executable — path to the running Python binary. Sizes: sys.getsizeof(obj) → bytes (shallow size); sys.maxsize — max int for a platform pointer. Byte order: sys.byteorder"little" or "big". Recursion: sys.getrecursionlimit() / sys.setrecursionlimit(n). Exception: sys.exc_info()(type, value, traceback) — only meaningful inside an except block; prefer traceback module for formatting. Trace hooks: sys.settrace(fn) / sys.setprofile(fn) — per-frame debugging and profiling. Claude Code generates CLI argument processors, stream redirectors, import hooks, version guards, and memory profilers.

CLAUDE.md for sys

## sys Stack
- Stdlib: import sys
- Args:   sys.argv[1:]           # command-line arguments
- Exit:   sys.exit(0)            # clean exit; sys.exit("error msg") → code 1
- Path:   sys.path.insert(0, d)  # prepend to module search path
- Mods:   sys.modules["name"]    # cached module; del to force reimport
- Version: sys.version_info >= (3, 11)
- Size:   sys.getsizeof(obj)     # shallow bytes
- IO:     sys.stdout = open("log.txt", "w")  # redirect output

sys Interpreter State Pipeline

# app/sysutil.py — argv, streams, path, modules, version, tracing
from __future__ import annotations

import io
import sys
import traceback
from contextlib import contextmanager
from dataclasses import dataclass
from typing import Generator, TextIO


# ─────────────────────────────────────────────────────────────────────────────
# 1. argv helpers
# ─────────────────────────────────────────────────────────────────────────────

def script_name() -> str:
    """
    Return the name of the running script (argv[0] basename).

    Example:
        print(f"Usage: {script_name()} <input> <output>")
    """
    import os
    return os.path.basename(sys.argv[0]) if sys.argv else "<stdin>"


def argv_flags() -> dict[str, "str | bool"]:
    """
    Parse --key=value and --flag arguments from sys.argv[1:].
    Returns {key: value_str} for --key=value, {key: True} for --flag.

    Example:
        flags = argv_flags()
        verbose = flags.get("verbose", False)
        output  = flags.get("output", "out.txt")
    """
    result: dict[str, "str | bool"] = {}
    for arg in sys.argv[1:]:
        if arg.startswith("--"):
            if "=" in arg:
                key, val = arg[2:].split("=", 1)
                result[key] = val
            else:
                result[arg[2:]] = True
    return result


def require_args(n: int, usage: str = "") -> list[str]:
    """
    Assert that at least n positional arguments were given, or exit with usage.

    Example:
        src, dest = require_args(2, "src dest")
        # exits with usage if fewer than 2 args
    """
    args = sys.argv[1:]
    if len(args) < n:
        prog = script_name()
        sys.exit(f"Usage: {prog} {usage}")
    return args


# ─────────────────────────────────────────────────────────────────────────────
# 2. Stream redirect context managers
# ─────────────────────────────────────────────────────────────────────────────

@contextmanager
def capture_stdout() -> Generator[io.StringIO, None, None]:
    """
    Context manager: capture sys.stdout into a StringIO buffer.
    Yields the buffer; restores stdout on exit.

    Example:
        with capture_stdout() as buf:
            print("captured!")
        assert "captured" in buf.getvalue()
    """
    buf = io.StringIO()
    old = sys.stdout
    sys.stdout = buf
    try:
        yield buf
    finally:
        sys.stdout = old


@contextmanager
def capture_stderr() -> Generator[io.StringIO, None, None]:
    """Capture sys.stderr into a StringIO buffer."""
    buf = io.StringIO()
    old = sys.stderr
    sys.stderr = buf
    try:
        yield buf
    finally:
        sys.stderr = old


@contextmanager
def redirect_stdout(stream: TextIO) -> Generator[None, None, None]:
    """
    Redirect sys.stdout to stream for the duration of the block.

    Example:
        with open("log.txt", "w") as f, redirect_stdout(f):
            print("goes to file")
    """
    old = sys.stdout
    sys.stdout = stream
    try:
        yield
    finally:
        sys.stdout = old


@contextmanager
def suppress_output() -> Generator[None, None, None]:
    """Discard all stdout and stderr output in the block."""
    null = open(io.os.devnull, "w") if hasattr(io, "os") else io.StringIO()
    dev_null = io.StringIO()
    old_out, old_err = sys.stdout, sys.stderr
    sys.stdout = dev_null
    sys.stderr = dev_null
    try:
        yield
    finally:
        sys.stdout = old_out
        sys.stderr = old_err


# ─────────────────────────────────────────────────────────────────────────────
# 3. Module cache utilities
# ─────────────────────────────────────────────────────────────────────────────

def force_reimport(module_name: str) -> object:
    """
    Remove a module from sys.modules and reimport it.
    Useful in long-running processes that hot-reload code.

    Example:
        force_reimport("myapp.config")
        import myapp.config  # gets the fresh version
    """
    import importlib
    sys.modules.pop(module_name, None)
    return importlib.import_module(module_name)


def is_imported(module_name: str) -> bool:
    """Return True if a module has been imported (is in sys.modules)."""
    return module_name in sys.modules


def list_submodules(package: str) -> list[str]:
    """
    Return names of all loaded modules that belong to package.

    Example:
        list_submodules("xml")   # ["xml", "xml.etree", "xml.etree.ElementTree", ...]
    """
    prefix = package + "."
    return [
        name for name in sys.modules
        if name == package or name.startswith(prefix)
    ]


# ─────────────────────────────────────────────────────────────────────────────
# 4. Version and platform guards
# ─────────────────────────────────────────────────────────────────────────────

def require_python(major: int, minor: int = 0) -> None:
    """
    Exit with a message if the Python version is older than required.

    Example:
        require_python(3, 11)
    """
    if sys.version_info < (major, minor):
        sys.exit(
            f"Python {major}.{minor}+ required; "
            f"running {sys.version_info.major}.{sys.version_info.minor}"
        )


def python_info() -> dict[str, object]:
    """
    Return a dict with Python version, platform, executable, and byte order.

    Example:
        info = python_info()
        print(info["version"])
    """
    return {
        "version":    f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
        "platform":   sys.platform,
        "executable": sys.executable,
        "byteorder":  sys.byteorder,
        "maxsize":    sys.maxsize,
        "encoding":   sys.getdefaultencoding(),
        "fs_encoding": sys.getfilesystemencoding(),
    }


# ─────────────────────────────────────────────────────────────────────────────
# 5. Memory sizing helpers
# ─────────────────────────────────────────────────────────────────────────────

def shallow_size(obj: object) -> int:
    """Return sys.getsizeof(obj) in bytes (shallow — does not recurse)."""
    return sys.getsizeof(obj)


def deep_size(obj: object, seen: "set | None" = None) -> int:
    """
    Recursively estimate total memory of obj and its referents.
    Handles cycles via a seen-set.

    Example:
        data = {"a": list(range(1000)), "b": "hello"}
        print(f"{deep_size(data):,} bytes")
    """
    if seen is None:
        seen = set()
    obj_id = id(obj)
    if obj_id in seen:
        return 0
    seen.add(obj_id)
    size = sys.getsizeof(obj)
    if isinstance(obj, dict):
        size += sum(deep_size(k, seen) + deep_size(v, seen) for k, v in obj.items())
    elif isinstance(obj, (list, tuple, set, frozenset)):
        size += sum(deep_size(item, seen) for item in obj)
    elif hasattr(obj, "__dict__"):
        size += deep_size(obj.__dict__, seen)
    return size


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

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

    # ── python_info ───────────────────────────────────────────────────────────
    print("\n--- python_info ---")
    for k, v in python_info().items():
        print(f"  {k}: {v}")

    # ── capture_stdout ────────────────────────────────────────────────────────
    print("\n--- capture_stdout ---")
    with capture_stdout() as buf:
        print("hello from captured stdout")
        print("line two")
    output = buf.getvalue()
    print(f"  captured {len(output)} chars: {output.strip()!r}")

    # ── capture_stderr ────────────────────────────────────────────────────────
    print("\n--- capture_stderr ---")
    with capture_stderr() as ebuf:
        import warnings
        warnings.warn("test warning", UserWarning, stacklevel=1)
    err = ebuf.getvalue()
    print(f"  stderr had content: {bool(err)}")

    # ── is_imported / list_submodules ─────────────────────────────────────────
    print("\n--- sys.modules helpers ---")
    print(f"  is_imported('json'):   {is_imported('json')}")
    import json
    print(f"  is_imported('json'):   {is_imported('json')}")
    print(f"  xml submodules: {list_submodules('xml')[:4]}")

    # ── shallow_size / deep_size ──────────────────────────────────────────────
    print("\n--- memory sizing ---")
    data = list(range(100))
    print(f"  shallow list[100]: {shallow_size(data)} bytes")
    print(f"  deep    list[100]: {deep_size(data)} bytes")

    d = {"key": [1, 2, 3], "msg": "hello world"}
    print(f"  deep    dict: {deep_size(d)} bytes")

    # ── argv_flags simulation ─────────────────────────────────────────────────
    print("\n--- argv_flags ---")
    orig = sys.argv[:]
    sys.argv = ["demo.py", "--verbose", "--output=result.txt", "--count=5"]
    flags = argv_flags()
    print(f"  flags: {flags}")
    sys.argv = orig

    # ── recursion limit ───────────────────────────────────────────────────────
    print("\n--- recursion limit ---")
    print(f"  getrecursionlimit(): {sys.getrecursionlimit()}")

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

For the os module alternative — os.environ, os.getpid(), os.getcwd(), os.path — handle OS-level process state, environment variables, and filesystem operations; sys handles Python interpreter state (argv, streams, path, modules, version); use os for process/filesystem concerns and sys for interpreter concerns — they are complementary, not alternatives. For the argparse / click alternatives — argparse.ArgumentParser and click turn sys.argv into structured, validated, documented options and subcommands — use argparse or click for any non-trivial CLI; use sys.argv directly only for the simplest single-argument scripts or when implementing your own argument parsing layer. The Claude Skills 360 bundle includes sys skill sets covering script_name()/argv_flags()/require_args() argv utilities, capture_stdout()/capture_stderr()/redirect_stdout()/suppress_output() stream redirectors, force_reimport()/is_imported()/list_submodules() module cache helpers, require_python()/python_info() version and platform guards, and shallow_size()/deep_size() memory sizing utilities. Start with the free tier to try interpreter state patterns and sys 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