Claude Code for errno: Python System Error Code Constants — Claude Skills 360 Blog
Blog / AI / Claude Code for errno: Python System Error Code Constants
AI

Claude Code for errno: Python System Error Code Constants

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

Python’s errno module exposes POSIX system error number constants and a mapping to their symbolic names. import errno. Constants: errno.ENOENT (2), errno.EACCES (13), errno.EEXIST (17), errno.EISDIR (21), errno.ENOTDIR (20), errno.ENOTEMPTY (39), errno.EAGAIN / errno.EWOULDBLOCK (11/11 on Linux), errno.EINTR (4), errno.EPIPE (32), errno.ECONNREFUSED (111), errno.ETIMEDOUT (110), errno.EADDRINUSE (98), errno.ENOMEM (12), errno.E2BIG (7), errno.EBUSY (16). Look up by number: errno.errorcode[n]"ENOENT" string; os.strerror(n)"No such file or directory". Check an OSError: e.errno == errno.ENOENT — the .errno attribute on OSError subclasses (FileNotFoundError, PermissionError, IsADirectoryError, etc.) holds the error number. Platform notes: not all constants exist on all platforms; use hasattr(errno, "ENOENT") or wrap in try/except AttributeError. Network codes: errno.ECONNRESET (104), errno.ENETUNREACH (101), errno.ENOPROTOOPT (92). Claude Code generates error-specific exception handlers, retry logic, network error classifiers, and portable cross-platform error message formatters.

CLAUDE.md for errno

## errno Stack
- Stdlib: import errno, os
- Check:  except OSError as e: if e.errno == errno.ENOENT: ...
- Name:   errno.errorcode[e.errno]        # "ENOENT"
- Msg:    os.strerror(e.errno)            # "No such file or directory"
- Common: ENOENT EACCES EEXIST EAGAIN EPIPE ECONNREFUSED ETIMEDOUT
- Note:   Python 3 maps errno to named exceptions:
-         ENOENT → FileNotFoundError  EACCES → PermissionError

errno Error Code Pipeline

# app/errnoutil.py — error checks, retry, classifiers, formatter
from __future__ import annotations

import errno
import os
import socket
import time
from dataclasses import dataclass
from typing import Callable


# ─────────────────────────────────────────────────────────────────────────────
# 1. Error code inspection helpers
# ─────────────────────────────────────────────────────────────────────────────

def errno_name(code: int) -> str:
    """
    Return the symbolic name for an errno code ("ENOENT", "EACCES", ...).
    Falls back to the decimal string if unknown.

    Example:
        print(errno_name(2))    # "ENOENT"
        print(errno_name(13))   # "EACCES"
    """
    return errno.errorcode.get(code, str(code))


def errno_message(code: int) -> str:
    """
    Return the human-readable strerror message for an errno code.

    Example:
        print(errno_message(2))   # "No such file or directory"
    """
    return os.strerror(code)


def oserror_info(exc: OSError) -> dict:
    """
    Return a structured dict with errno, name, message, and filename from an OSError.

    Example:
        try:
            open("/nonexistent")
        except OSError as e:
            print(oserror_info(e))
    """
    code = exc.errno or 0
    return {
        "errno":    code,
        "name":     errno_name(code),
        "message":  errno_message(code),
        "filename": exc.filename,
        "strerror": exc.strerror or "",
    }


# ─────────────────────────────────────────────────────────────────────────────
# 2. Error category classifiers
# ─────────────────────────────────────────────────────────────────────────────

_TRANSIENT_ERRNO = frozenset(filter(None, [
    getattr(errno, "EAGAIN",        None),
    getattr(errno, "EWOULDBLOCK",   None),
    getattr(errno, "EINTR",         None),
    getattr(errno, "ETIMEDOUT",     None),
    getattr(errno, "ENETUNREACH",   None),
    getattr(errno, "ECONNRESET",    None),
    getattr(errno, "ECONNABORTED",  None),
]))

_PERMISSION_ERRNO = frozenset(filter(None, [
    getattr(errno, "EACCES",  None),
    getattr(errno, "EPERM",   None),
]))

_NOT_FOUND_ERRNO = frozenset(filter(None, [
    getattr(errno, "ENOENT",  None),
    getattr(errno, "ENODEV",  None),
    getattr(errno, "ENXIO",   None),
]))

_NETWORK_ERRNO = frozenset(filter(None, [
    getattr(errno, "ECONNREFUSED",  None),
    getattr(errno, "ECONNRESET",    None),
    getattr(errno, "ETIMEDOUT",     None),
    getattr(errno, "ENETUNREACH",   None),
    getattr(errno, "EHOSTUNREACH",  None),
    getattr(errno, "EPIPE",         None),
]))


def is_transient(exc: OSError) -> bool:
    """
    Return True if the error is likely transient and worth retrying.

    Example:
        except OSError as e:
            if is_transient(e):
                retry()
            else:
                raise
    """
    return exc.errno in _TRANSIENT_ERRNO


def is_permission_error(exc: OSError) -> bool:
    """Return True for EACCES / EPERM."""
    return exc.errno in _PERMISSION_ERRNO


def is_not_found(exc: OSError) -> bool:
    """Return True for ENOENT and related not-found codes."""
    return exc.errno in _NOT_FOUND_ERRNO


def is_network_error(exc: OSError) -> bool:
    """Return True for connection/network-related errno codes."""
    return exc.errno in _NETWORK_ERRNO


def error_category(exc: OSError) -> str:
    """
    Classify an OSError into a string category for structured logging.

    Example:
        except OSError as e:
            log.warning("io error", category=error_category(e))
    """
    if is_permission_error(exc):
        return "permission"
    if is_not_found(exc):
        return "not_found"
    if is_network_error(exc):
        return "network"
    if is_transient(exc):
        return "transient"
    return "other"


# ─────────────────────────────────────────────────────────────────────────────
# 3. Retry with errno-aware backoff
# ─────────────────────────────────────────────────────────────────────────────

def retry_on_transient(
    fn: Callable,
    *args: object,
    max_attempts: int = 5,
    base_delay: float = 0.1,
    backoff: float = 2.0,
    **kwargs: object,
) -> object:
    """
    Retry fn on transient OSError (EAGAIN, EINTR, ECONNRESET, etc.).
    Raises immediately on non-transient errors or after max_attempts.

    Example:
        result = retry_on_transient(socket.connect, (host, port), max_attempts=3)
    """
    last_exc: OSError | None = None
    delay = base_delay
    for attempt in range(1, max_attempts + 1):
        try:
            return fn(*args, **kwargs)
        except OSError as e:
            if not is_transient(e):
                raise
            last_exc = e
            if attempt < max_attempts:
                time.sleep(delay)
                delay = min(delay * backoff, 30.0)
    assert last_exc is not None
    raise last_exc


# ─────────────────────────────────────────────────────────────────────────────
# 4. Safe file operations with errno handling
# ─────────────────────────────────────────────────────────────────────────────

def safe_unlink(path: "str | os.PathLike") -> bool:
    """
    Remove a file, ignoring ENOENT (already gone). Returns True if deleted.

    Example:
        safe_unlink("/tmp/lock.pid")
    """
    try:
        os.unlink(str(path))
        return True
    except OSError as e:
        if e.errno == errno.ENOENT:
            return False
        raise


def safe_mkdir(path: "str | os.PathLike") -> bool:
    """
    Create a directory, ignoring EEXIST. Returns True if newly created.

    Example:
        safe_mkdir("/data/cache")
    """
    try:
        os.mkdir(str(path))
        return True
    except OSError as e:
        if e.errno == errno.EEXIST:
            return False
        raise


def read_if_exists(path: "str | os.PathLike", default: str = "") -> str:
    """
    Read a text file, returning default on ENOENT.

    Example:
        config = read_if_exists("/etc/myapp/config.ini")
    """
    try:
        with open(str(path)) as f:
            return f.read()
    except OSError as e:
        if e.errno == errno.ENOENT:
            return default
        raise


def is_port_in_use(port: int, host: str = "127.0.0.1") -> bool:
    """
    Return True if a TCP port is already bound (EADDRINUSE).

    Example:
        if is_port_in_use(8080):
            print("port 8080 is busy")
    """
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            s.bind((host, port))
            return False
        except OSError as e:
            if e.errno == errno.EADDRINUSE:
                return True
            raise


# ─────────────────────────────────────────────────────────────────────────────
# 5. errno reference table
# ─────────────────────────────────────────────────────────────────────────────

_IMPORTANT_ERRORS = [
    "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", "ENXIO", "E2BIG",
    "ENOEXEC", "EBADF", "ECHILD", "EAGAIN", "ENOMEM", "EACCES", "EFAULT",
    "EBUSY", "EEXIST", "EXDEV", "ENODEV", "ENOTDIR", "EISDIR", "EINVAL",
    "ENFILE", "EMFILE", "ENOSPC", "ESPIPE", "EROFS", "EPIPE", "ERANGE",
    "EDEADLK", "ENAMETOOLONG", "ENOTEMPTY", "ELOOP", "EWOULDBLOCK",
    "ENOMSG", "ENOLINK", "EPROTO", "EMULTIHOP", "EBADMSG", "ENOTCONN",
    "ECONNREFUSED", "ECONNRESET", "ECONNABORTED", "ETIMEDOUT",
    "EADDRINUSE", "EADDRNOTAVAIL", "ENETUNREACH", "EHOSTUNREACH", "EPIPE",
]


def errno_table() -> list[dict]:
    """
    Return a list of dicts for common errno constants available on this platform.

    Example:
        for row in errno_table():
            print(f"  {row['code']:3d}  {row['name']:20s}  {row['message']}")
    """
    result = []
    for name in _IMPORTANT_ERRORS:
        val = getattr(errno, name, None)
        if val is not None:
            result.append({
                "code":    val,
                "name":    name,
                "message": os.strerror(val),
            })
    return result


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

if __name__ == "__main__":
    import tempfile
    from pathlib import Path

    print("=== errno demo ===")

    # ── basic lookups ─────────────────────────────────────────────────────────
    print("\n--- errno name + message ---")
    for code in [errno.ENOENT, errno.EACCES, errno.EEXIST,
                 errno.EAGAIN, errno.EPIPE, errno.ECONNREFUSED]:
        print(f"  {code:3d}  {errno_name(code):20s}  {errno_message(code)}")

    # ── oserror_info ──────────────────────────────────────────────────────────
    print("\n--- oserror_info ---")
    try:
        open("/no/such/path/exists")
    except OSError as e:
        info = oserror_info(e)
        print(f"  {info}")

    # ── error_category ────────────────────────────────────────────────────────
    print("\n--- error_category ---")
    for code, desc in [
        (errno.ENOENT, "missing file"),
        (errno.EACCES, "permission denied"),
        (errno.EAGAIN, "would block"),
        (errno.ECONNREFUSED, "connection refused"),
    ]:
        exc = OSError(code, os.strerror(code))
        exc.errno = code
        print(f"  {desc}: category={error_category(exc)}")

    # ── safe_unlink / safe_mkdir ──────────────────────────────────────────────
    print("\n--- safe_unlink / safe_mkdir ---")
    with tempfile.TemporaryDirectory() as td:
        p = Path(td) / "lock.pid"
        print(f"  safe_unlink (missing): {safe_unlink(p)}")
        p.write_text("42")
        print(f"  safe_unlink (exists):  {safe_unlink(p)}")
        sub = Path(td) / "cache"
        print(f"  safe_mkdir (new):      {safe_mkdir(sub)}")
        print(f"  safe_mkdir (exists):   {safe_mkdir(sub)}")

    # ── is_port_in_use ────────────────────────────────────────────────────────
    print("\n--- is_port_in_use ---")
    with socket.socket() as s:
        s.bind(("127.0.0.1", 0))
        port = s.getsockname()[1]
        print(f"  port {port} (bound):   {is_port_in_use(port)}")
    print(f"  port {port} (free):    {is_port_in_use(port)}")

    # ── errno_table excerpt ───────────────────────────────────────────────────
    print("\n--- errno_table (first 8) ---")
    for row in errno_table()[:8]:
        print(f"  {row['code']:3d}  {row['name']:20s}  {row['message']}")

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

For the os.strerror alternative — os.strerror(code) returns the platform error message for a numeric code; it is the same call made internally by OSError.__str__() — use os.strerror when you have a raw integer errno and need the message without constructing an exception; use errno.errorcode for the symbolic name. For Python 3 named exceptions — FileNotFoundError (ENOENT), PermissionError (EACCES/EPERM), IsADirectoryError (EISDIR), NotADirectoryError (ENOTDIR), FileExistsError (EEXIST), BlockingIOError (EAGAIN/EWOULDBLOCK), TimeoutError (ETIMEDOUT), ConnectionRefusedError (ECONNREFUSED), BrokenPipeError (EPIPE) — these are subclasses of OSError that match except FileNotFoundError without checking .errno; use named exceptions for single-error catches in idiomatic Python 3 code; use errno constants when you need to handle multiple codes in one except OSError block or when writing cross-version code. The Claude Skills 360 bundle includes errno skill sets covering errno_name()/errno_message()/oserror_info() code inspection, is_transient()/is_permission_error()/is_not_found()/is_network_error()/error_category() classifiers, retry_on_transient() errno-aware backoff retry, safe_unlink()/safe_mkdir()/read_if_exists()/is_port_in_use() safe wrappers, and errno_table() reference listing. Start with the free tier to try error code patterns and errno 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