Claude Code for resource: Python Unix Resource Limits — Claude Skills 360 Blog
Blog / AI / Claude Code for resource: Python Unix Resource Limits
AI

Claude Code for resource: Python Unix Resource Limits

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

Python’s resource module (Unix/macOS only) reads and sets process resource limits and reports resource usage statistics. import resource. getrlimit: soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) — returns (soft, hard) tuple; RLIM_INFINITY = -1 means unlimited. setrlimit: resource.setrlimit(resource.RLIMIT_NOFILE, (soft, hard)) — unprivileged processes can raise soft up to hard; only root can raise hard. getrusage: ru = resource.getrusage(resource.RUSAGE_SELF) — returns struct_rusage; key fields: ru_utime (user CPU seconds), ru_stime (system CPU seconds), ru_maxrss (peak RSS in KB on Linux, bytes on macOS), ru_minflt/ru_majflt (minor/major page faults), ru_nvcsw/ru_nivcsw (voluntary/involuntary context switches), ru_inblock/ru_oublock (block I/O ops). RUSAGE_CHILDREN — usage of waited-for children. Common RLIMIT_* constants: RLIMIT_AS (virtual memory), RLIMIT_CORE, RLIMIT_CPU (seconds), RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_RSS, RLIMIT_STACK. Windows: not available; use psutil for cross-platform resource monitoring. Claude Code generates memory-limited workers, CPU-time sandboxes, open-fd maximizers, and resource usage reporters.

CLAUDE.md for resource

## resource Stack
- Stdlib: import resource
- Get:    soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
- Set:    resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft, hard))
- Usage:  ru = resource.getrusage(resource.RUSAGE_SELF)
-         ru.ru_utime  ru.ru_stime  ru.ru_maxrss  ru_minflt  ru_majflt
- Inf:    resource.RLIM_INFINITY   # -1, meaning "no limit"
- Note:   softlimit ≤ hardlimit; only root can raise hardlimit

resource Unix Resource Limits Pipeline

# app/resourceutil.py — read/set limits, maximize fds, sandbox, usage report
from __future__ import annotations

import os
import platform
import time
from dataclasses import dataclass

_RESOURCE_AVAILABLE = platform.system() != "Windows"
if _RESOURCE_AVAILABLE:
    import resource as _resource


# ─────────────────────────────────────────────────────────────────────────────
# 1. Limit read / write helpers
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class Limit:
    name:  str
    soft:  int    # -1 = RLIM_INFINITY
    hard:  int

    def is_unlimited(self) -> bool:
        return self.soft == -1

    def __str__(self) -> str:
        soft_s = "unlimited" if self.soft == -1 else str(self.soft)
        hard_s = "unlimited" if self.hard == -1 else str(self.hard)
        return f"{self.name:<18s}  soft={soft_s:<12s}  hard={hard_s}"


def get_limit(resource_id: int, name: str = "") -> Limit:
    """
    Read the current (soft, hard) limit for a resource constant.

    Example:
        lim = get_limit(resource.RLIMIT_NOFILE, "NOFILE")
        print(lim)
    """
    if not _RESOURCE_AVAILABLE:
        raise OSError("resource module not available on Windows")
    soft, hard = _resource.getrlimit(resource_id)
    return Limit(name=name or str(resource_id), soft=soft, hard=hard)


def set_soft_limit(resource_id: int, new_soft: int) -> None:
    """
    Set only the soft limit for a resource, keeping the hard limit unchanged.
    Raises ValueError if new_soft exceeds hard limit.

    Example:
        set_soft_limit(resource.RLIMIT_NOFILE, 65536)
    """
    if not _RESOURCE_AVAILABLE:
        raise OSError("resource module not available on Windows")
    _, hard = _resource.getrlimit(resource_id)
    if hard != _resource.RLIM_INFINITY and new_soft > hard:
        raise ValueError(
            f"Requested soft limit {new_soft} exceeds hard limit {hard}"
        )
    _resource.setrlimit(resource_id, (new_soft, hard))


def maximize_open_files() -> int:
    """
    Raise RLIMIT_NOFILE soft limit to the hard limit.
    Returns the new soft limit.
    Useful before servers that open many connections.

    Example:
        max_fds = maximize_open_files()
        print(f"Can now open {max_fds} file descriptors")
    """
    if not _RESOURCE_AVAILABLE:
        return 1024   # Windows default
    soft, hard = _resource.getrlimit(_resource.RLIMIT_NOFILE)
    if hard == _resource.RLIM_INFINITY:
        target = 1_048_576   # reasonable cap when hard is unlimited
    else:
        target = hard
    if soft < target:
        _resource.setrlimit(_resource.RLIMIT_NOFILE, (target, hard))
    return target


def all_limits() -> list[Limit]:
    """
    Return current soft/hard limits for all available RLIMIT_* constants.

    Example:
        for lim in all_limits():
            print(lim)
    """
    if not _RESOURCE_AVAILABLE:
        return []

    rlimit_names = [
        ("RLIMIT_AS",      getattr(_resource, "RLIMIT_AS",      None)),
        ("RLIMIT_CORE",    getattr(_resource, "RLIMIT_CORE",    None)),
        ("RLIMIT_CPU",     getattr(_resource, "RLIMIT_CPU",     None)),
        ("RLIMIT_DATA",    getattr(_resource, "RLIMIT_DATA",    None)),
        ("RLIMIT_FSIZE",   getattr(_resource, "RLIMIT_FSIZE",   None)),
        ("RLIMIT_MEMLOCK", getattr(_resource, "RLIMIT_MEMLOCK", None)),
        ("RLIMIT_MSGQUEUE",getattr(_resource, "RLIMIT_MSGQUEUE",None)),
        ("RLIMIT_NOFILE",  getattr(_resource, "RLIMIT_NOFILE",  None)),
        ("RLIMIT_NPROC",   getattr(_resource, "RLIMIT_NPROC",   None)),
        ("RLIMIT_RSS",     getattr(_resource, "RLIMIT_RSS",     None)),
        ("RLIMIT_RTPRIO",  getattr(_resource, "RLIMIT_RTPRIO",  None)),
        ("RLIMIT_SIGPENDING",getattr(_resource,"RLIMIT_SIGPENDING",None)),
        ("RLIMIT_STACK",   getattr(_resource, "RLIMIT_STACK",   None)),
    ]
    results = []
    for name, rid in rlimit_names:
        if rid is None:
            continue
        try:
            soft, hard = _resource.getrlimit(rid)
            results.append(Limit(name=name, soft=soft, hard=hard))
        except (OSError, ValueError):
            continue
    return results


# ─────────────────────────────────────────────────────────────────────────────
# 2. Process sandboxing
# ─────────────────────────────────────────────────────────────────────────────

def apply_sandbox(
    max_cpu_seconds: int | None = None,
    max_memory_bytes: int | None = None,
    max_file_size_bytes: int | None = None,
    max_open_files: int | None = None,
    no_core_dumps: bool = True,
) -> None:
    """
    Apply resource limits to restrict the current process.
    Intended for child processes before exec or for sandboxing worker threads.

    Example:
        apply_sandbox(max_cpu_seconds=5, max_memory_bytes=256*1024*1024)
    """
    if not _RESOURCE_AVAILABLE:
        return

    if no_core_dumps and hasattr(_resource, "RLIMIT_CORE"):
        _resource.setrlimit(_resource.RLIMIT_CORE, (0, 0))

    if max_cpu_seconds is not None and hasattr(_resource, "RLIMIT_CPU"):
        _resource.setrlimit(_resource.RLIMIT_CPU,
                            (max_cpu_seconds, max_cpu_seconds))

    if max_memory_bytes is not None:
        for res_name in ("RLIMIT_AS", "RLIMIT_DATA"):
            rid = getattr(_resource, res_name, None)
            if rid is None:
                continue
            try:
                _, hard = _resource.getrlimit(rid)
                cap = max_memory_bytes if hard == _resource.RLIM_INFINITY else min(max_memory_bytes, hard)
                _resource.setrlimit(rid, (cap, cap))
            except (OSError, ValueError):
                pass

    if max_file_size_bytes is not None and hasattr(_resource, "RLIMIT_FSIZE"):
        _resource.setrlimit(_resource.RLIMIT_FSIZE,
                            (max_file_size_bytes, max_file_size_bytes))

    if max_open_files is not None and hasattr(_resource, "RLIMIT_NOFILE"):
        try:
            _, hard = _resource.getrlimit(_resource.RLIMIT_NOFILE)
            cap = max_open_files if hard == _resource.RLIM_INFINITY else min(max_open_files, hard)
            _resource.setrlimit(_resource.RLIMIT_NOFILE, (cap, hard))
        except (OSError, ValueError):
            pass


# ─────────────────────────────────────────────────────────────────────────────
# 3. Resource usage
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class UsageSnapshot:
    user_time:       float   # seconds
    sys_time:        float
    wall_time:       float
    max_rss_kb:      int     # KB on Linux; bytes / 1024 on macOS
    minor_faults:    int
    major_faults:    int
    voluntary_csw:   int
    involuntary_csw: int
    block_in:        int
    block_out:       int

    @property
    def cpu_time(self) -> float:
        return self.user_time + self.sys_time

    def __str__(self) -> str:
        return (
            f"cpu={self.cpu_time:.3f}s  "
            f"(user={self.user_time:.3f}s  sys={self.sys_time:.3f}s)  "
            f"wall={self.wall_time:.3f}s  "
            f"rss={self.max_rss_kb:,d}KB  "
            f"faults={self.minor_faults}/{self.major_faults}  "
            f"csw={self.voluntary_csw}/{self.involuntary_csw}"
        )


def _rss_kb(raw: int) -> int:
    """Normalize max_rss: bytes on macOS → KB; already KB on Linux."""
    if platform.system() == "Darwin":
        return raw // 1024
    return raw


def get_usage(who: int | None = None) -> UsageSnapshot:
    """
    Return a resource usage snapshot for the current process or its children.
    who: resource.RUSAGE_SELF (default) or resource.RUSAGE_CHILDREN.

    Example:
        before = get_usage()
        run_heavy_work()
        after = get_usage()
    """
    if not _RESOURCE_AVAILABLE:
        return UsageSnapshot(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
    if who is None:
        who = _resource.RUSAGE_SELF
    ru = _resource.getrusage(who)
    return UsageSnapshot(
        user_time=ru.ru_utime,
        sys_time=ru.ru_stime,
        wall_time=time.monotonic(),
        max_rss_kb=_rss_kb(ru.ru_maxrss),
        minor_faults=ru.ru_minflt,
        major_faults=ru.ru_majflt,
        voluntary_csw=ru.ru_nvcsw,
        involuntary_csw=ru.ru_nivcsw,
        block_in=ru.ru_inblock,
        block_out=ru.ru_oublock,
    )


def delta_usage(before: UsageSnapshot, after: UsageSnapshot) -> UsageSnapshot:
    """
    Compute the difference between two usage snapshots.

    Example:
        before = get_usage()
        work()
        after = get_usage()
        print(delta_usage(before, after))
    """
    return UsageSnapshot(
        user_time=after.user_time - before.user_time,
        sys_time=after.sys_time - before.sys_time,
        wall_time=after.wall_time - before.wall_time,
        max_rss_kb=max(after.max_rss_kb, before.max_rss_kb),   # peak, not delta
        minor_faults=after.minor_faults - before.minor_faults,
        major_faults=after.major_faults - before.major_faults,
        voluntary_csw=after.voluntary_csw - before.voluntary_csw,
        involuntary_csw=after.involuntary_csw - before.involuntary_csw,
        block_in=after.block_in - before.block_in,
        block_out=after.block_out - before.block_out,
    )


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

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

    if not _RESOURCE_AVAILABLE:
        print("  resource not available on Windows — skipping")
        raise SystemExit(0)

    # ── all_limits ─────────────────────────────────────────────────────────────
    print("\n--- all_limits ---")
    for lim in all_limits():
        print(f"  {lim}")

    # ── maximize_open_files ────────────────────────────────────────────────────
    print("\n--- maximize_open_files ---")
    old_soft, old_hard = _resource.getrlimit(_resource.RLIMIT_NOFILE)
    new_max = maximize_open_files()
    cur_soft, _ = _resource.getrlimit(_resource.RLIMIT_NOFILE)
    print(f"  before: soft={old_soft}  hard={old_hard}")
    print(f"  after:  soft={cur_soft}  (maximize returned {new_max})")

    # ── get_usage ──────────────────────────────────────────────────────────────
    print("\n--- get_usage ---")
    before = get_usage()

    # Do some CPU work to generate measurable usage
    total = sum(i * i for i in range(500_000))

    after = get_usage()
    diff = delta_usage(before, after)
    print(f"  before: {before}")
    print(f"  after:  {after}")
    print(f"  delta:  {diff}")
    print(f"  sum={total}")

    # ── apply_sandbox in child ─────────────────────────────────────────────────
    print("\n--- apply_sandbox (in child process) ---")
    pid = os.fork()
    if pid == 0:
        # Child: apply limits and try to exceed them
        apply_sandbox(
            max_cpu_seconds=10,
            max_open_files=64,
            no_core_dumps=True,
        )
        nofile_soft, _ = _resource.getrlimit(_resource.RLIMIT_NOFILE)
        print(f"  child RLIMIT_NOFILE soft: {nofile_soft}")
        os._exit(0)
    else:
        _, status = os.waitpid(pid, 0)
        print(f"  child exited with status: {os.waitstatus_to_exitcode(status)}")

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

For the psutil alternative — psutil (PyPI) provides cross-platform process memory info (process.memory_info().rss), CPU percent, open files, and connections with a unified API that works on Windows, Linux, and macOS — use psutil when you need cross-platform resource monitoring, live process trees, or percent-based metrics that resource doesn’t expose; use resource when you need to set OS enforcement limits (setrlimit) rather than just observe usage, or when you want zero dependencies and are targeting Linux/macOS only. For the signal alternative — signal.setitimer(signal.ITIMER_VIRTUAL, seconds) sends SIGVTALRM after a CPU-time interval and signal.alarm(n) sends SIGALRM after wall-clock seconds — use signal timers for soft CPU enforcement that triggers a Python exception handler; use resource.setrlimit(RLIMIT_CPU) for hard kernel-enforced CPU limits that send SIGXCPU and cannot be bypassed by user code even after a fork/exec. The Claude Skills 360 bundle includes resource skill sets covering Limit dataclass with get_limit()/set_soft_limit()/maximize_open_files()/all_limits() limit management, apply_sandbox() for CPU/memory/file-size/fd sandboxing, UsageSnapshot with get_usage()/delta_usage() resource accounting, and platform-aware RSS normalization. Start with the free tier to try resource limit patterns and resource 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