The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Install a handlerprevious = signal.signal(signal.SIGTERM, handle_shutdown)View examples
Check the main threadis_main = threading.current_thread() is threading.main_thread()View examples
List supported signalssupported = signal.valid_signals()View examples
Request graceful stopdef handler(signum, frame): shutdown.set()View examples
Wait interruptiblyrequested = shutdown.wait(timeout=1.0)View examples
Restore a dispositionsignal.signal(signal.SIGTERM, previous)View examples
Schedule SIGALRMremaining = signal.alarm(seconds)View examples
Schedule a real-time timerprevious = signal.setitimer(signal.ITIMER_REAL, delay, interval)View examples
Block signals in one threadprevious = signal.pthread_sigmask(signal.SIG_BLOCK, signals)View examples
Read with a defaultmode = os.getenv('APP_MODE', 'production')View examples
Require a variabledatabase_url = os.environ['DATABASE_URL']View examples
Copy the environmentenvironment = os.environ.copy()View examples
Set a process variableos.environ['APP_MODE'] = 'test'View examples
Remove a process variableos.environ.pop('APP_MODE', None)View examples
Reload external changesos.reload_environ()View examples
Pass a child environmentsubprocess.run(argv, env=child_env, check=True)View examples
Override selected child valueschild_env = os.environ | {'APP_MODE': 'batch'}View examples
Expand environment syntaxexpanded = os.path.expandvars(template)View examples
Read a bytes environmentraw = os.environb.get(b'KEY')View examples
Check bytes environment supportavailable = os.supports_bytes_environView examples

Signals are asynchronous operating-system notifications, while environment variables are inherited process configuration. Python runs signal handlers in the main thread at a later bytecode checkpoint, not inside the low-level handler. Robust services translate signals into simple shutdown state, keep cleanup in ordinary control flow, snapshot validated configuration early, and pass deliberate environments to child processes.

Step by step

Detailed examples

01

Understand Python's deferred signal model

Python's low-level handler sets a flag and the interpreter later calls the Python handler in the main thread. A long-running C operation may delay that call. Only the main thread of the main interpreter can install handlers, and signals cannot provide inter-thread delivery guarantees; use threading.Event, queues, or cancellation primitives for thread coordination.

Call a minimal handler deterministically
import signal

received: list[int] = []
def handle(signum, frame) -> None:
    received.append(signum)

handle(signal.SIGTERM, None)
print(received == [signal.SIGTERM])
print(signal.Signals(received[0]).name)
Output
True
SIGTERM
Back to quick reference ↑
02

Translate termination into ordinary control flow

A handler should perform minimal work such as setting an Event or boolean. The main loop then stops accepting work, drains or cancels within a deadline, flushes durable state, and exits. Logging, locks, arbitrary callbacks, and exceptions inside handlers can interact with code interrupted at an inconvenient point; repeated signals may need a documented force-exit policy.

Drive cleanup from normal code
class StopFlag:
    requested = False

flag = StopFlag()
def handler(signum, frame) -> None:
    flag.requested = True

handler(15, None)
if flag.requested:
    print("stop intake")
    print("cleanup complete")
Output
stop intake
cleanup complete
Back to quick reference ↑
03

Treat timers and signal masks as Unix-specific tools

alarm and setitimer schedule process signals and can overwrite a timer owned by another library. pthread_sigmask changes the calling thread's signal mask on supporting Unix platforms; new threads inherit that mask. Use feature detection and restore prior state in finally. Windows exposes a smaller, different signal model and console control events have special process-group rules.

Feature-detect platform-specific signal APIs
import signal

features = {
    "alarm": hasattr(signal, "alarm"),
    "pthread_sigmask": hasattr(signal, "pthread_sigmask"),
    "setitimer": hasattr(signal, "setitimer"),
}
print(all(isinstance(value, bool) for value in features.values()))
print(sorted(features))
Output
True
['alarm', 'pthread_sigmask', 'setitimer']
Back to quick reference ↑
04

Read environment configuration with a schema

os.environ is a mutable string-to-string mapping captured during interpreter startup. getenv distinguishes a missing key only when the default is chosen appropriately; an empty value is not the same as absence. Parse and validate booleans, numbers, lists, encodings, and URLs once near startup, and avoid scattering implicit defaults through business logic.

Parse a strict environment boolean
def parse_bool(value: str) -> bool:
    normalized = value.strip().casefold()
    if normalized not in {"true", "false"}:
        raise ValueError("expected true or false")
    return normalized == "true"

print(parse_bool(" TRUE "))
try:
    parse_bool("yes")
except ValueError as error:
    print(error)
Output
True
expected true or false
Back to quick reference ↑
05

Modify os.environ instead of calling putenv directly

Assigning or deleting os.environ entries updates the process environment through the platform API. putenv does not update the mapping, so direct mapping edits are preferred. On Windows keys are normalized to uppercase; on Unix environb may expose bytes when supported. Environment mutation is process-global and unsafe as request-local state.

Temporarily override and restore a variable
import os

name = "CMDMEMO_EXAMPLE_MODE"
previous = os.environ.get(name)
try:
    os.environ[name] = "test"
    print(os.environ[name])
finally:
    if previous is None:
        os.environ.pop(name, None)
    else:
        os.environ[name] = previous
print(os.environ.get(name) == previous)
Output
test
True
Back to quick reference ↑
06

Pass an allowlisted environment to child processes

Children inherit the parent's environment by default, which can leak credentials and alter executable, locale, proxy, or library resolution. Construct a minimal environment from reviewed keys and pass it with subprocess env. On Windows include variables required by the target runtime; on POSIX use absolute executables or a controlled PATH. Never log the full environment.

Build a redacted child environment
parent = {"PATH": "/usr/bin", "APP_TOKEN": "secret", "LANG": "C.UTF-8"}
allowed = {key: parent[key] for key in ("PATH", "LANG") if key in parent}
allowed["APP_MODE"] = "batch"
for key in sorted(allowed):
    print(key, allowed[key])
Output
APP_MODE batch
LANG C.UTF-8
PATH /usr/bin
Back to quick reference ↑
07

Keep secrets out of ambient process state when possible

Environment variables are convenient but may be exposed to child processes, crash reports, diagnostics, orchestration metadata, or same-user inspection depending on the platform. Prefer a secret manager or inherited descriptor when the threat model requires it, scope access narrowly, and rotate independently. Deleting a variable does not erase copies already made by libraries or the operating system.

Redact sensitive configuration by key policy
environment = {"APP_MODE": "prod", "API_TOKEN": "abc", "PORT": "8080"}
safe = {
    key: ("<redacted>" if key.endswith(("TOKEN", "PASSWORD", "SECRET")) else value)
    for key, value in environment.items()
}
for key in sorted(safe):
    print(f"{key}={safe[key]}")
Output
API_TOKEN=<redacted>
APP_MODE=prod
PORT=8080
Back to quick reference ↑

Local code tester

Validate process configuration

Parse a small environment-style mapping into typed configuration without reading or modifying the host environment.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software Foundationsignal — Set handlers for asynchronous eventsdocs.python.org
  2. Python Software Foundationos — Miscellaneous operating system interfacesdocs.python.org
  3. Python Software Foundationsubprocess — Subprocess managementdocs.python.org
  4. Python Software Foundationthreading — Thread-based parallelismdocs.python.org
  5. Python Software FoundationPython Initialization Configurationdocs.python.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback