os.sched_getaffinity
pid 0 always means "the calling process" (for affinity: the calling thread). The affinity mask is a set of CPU numbers; policies are int constants; priorities travel in an immutable sched_param. The docs say these functions exist "only on some Unix platforms": Linux has them all, Windows has none.
Common call
len(os.sched_getaffinity(0))
Returns
number of CPUs this process may use
Replaces
the taskset and chrt commands
Watch out
The mask is an iterable of CPU numbers, not a count or a bitmask int
os.sched_getaffinity(pidpid — The target process; 0 = the calling process (thread, for affinity).type: int · required, /) / os.sched_setaffinity(pid, maskmask — sched_setaffinity: CPU numbers the process may use, e.g. {0, 1}.type: iterable of int · required, /) / os.sched_setscheduler(pid, policypolicy — A SCHED_* constant, optionally OR-ed with SCHED_RESET_ON_FORK.type: int · required, paramparam — sched_setscheduler / sched_setparam: os.sched_param(sched_priority).type: os.sched_param · required, /)
→ set[int]
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| pid | int | yes | The target process; 0 = the calling process (thread, for affinity). |
| mask | iterable of int | yes | sched_setaffinity: CPU numbers the process may use, e.g. {0, 1}. |
| policy | int | yes | A SCHED_* constant, optionally OR-ed with SCHED_RESET_ON_FORK. |
| param | os.sched_param | yes | sched_setscheduler / sched_setparam: os.sched_param(sched_priority). |
Return value
set[int] — sched_getaffinity: the set of CPU numbers the process may run on. Others: an int policy/priority, a sched_param, a float interval, or None.
Common patterns
Usable CPUs (Linux)
Respects taskset and container CPU sets, unlike cpu_count().
import os workers = len(os.sched_getaffinity(0))
Pin the current process to two CPUs
Any iterable of CPU numbers works.
import os os.sched_setaffinity(0, {0, 1})
Real-time FIFO scheduling (needs privileges)
Priority must be within the policy range.
import os prio = os.sched_get_priority_min(os.SCHED_FIFO) os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(prio))
Background batch policy
SCHED_IDLE / SCHED_BATCH need no privileges and a priority of 0.
import os os.sched_setscheduler(0, os.SCHED_IDLE, os.sched_param(0))
Examples
1. Same availability for the whole family
import os
len({hasattr(os, n) for n in ('sched_getaffinity', 'sched_setaffinity', 'sched_param', 'SCHED_FIFO')})
Returns
12. Usable CPUs never exceed the total
import os
usable = len(os.sched_getaffinity(0)) if hasattr(os, 'sched_getaffinity') else os.cpu_count()
1 <= usable <= os.cpu_count()
Returns
True3. A mask is a set of CPU numbers
all_cpus = set(range(8))
all_cpus - {0}
Returns
{1, 2, 3, 4, 5, 6, 7}4. SCHED_RESET_ON_FORK is a flag bit (Linux value)
SCHED_FIFO, SCHED_RESET_ON_FORK = 1, 0x40000000
policy = SCHED_FIFO | SCHED_RESET_ON_FORK
(policy & ~SCHED_RESET_ON_FORK, bool(policy & SCHED_RESET_ON_FORK))
Returns
(1, True)5. Clamp a requested priority into the FIFO range (1..99 on Linux)
lo, hi = 1, 99
[max(lo, min(hi, p)) for p in (0, 50, 200)]
Returns
[1, 50, 99]Pitfalls
1. Passing a CPU count as the mask
sched_setaffinity wants the CPU numbers. On Linux, os.sched_setaffinity(0, 4) raises this same TypeError; pass range(4) for CPUs 0-3.
mask = 4
mask = 4 set(mask)
TypeError: 'int' object is not iterable
mask = range(4)
mask = range(4) set(mask)
{0, 1, 2, 3}
2. Using a real-time priority with SCHED_OTHER
The normal policies (OTHER, BATCH, IDLE) only accept priority 0; FIFO and RR use 1 to 99 on Linux. On Linux, sched_setscheduler(0, SCHED_OTHER, sched_param(50)) raises OSError with errno 22 (EINVAL). Ask sched_get_priority_min / max instead of hard-coding.
priority 50 for OTHER
ranges = {'SCHED_OTHER': (0, 0), 'SCHED_FIFO': (1, 99)} # Linux values lo, hi = ranges['SCHED_OTHER'] lo <= 50 <= hi
False
stay in the range
ranges = {'SCHED_OTHER': (0, 0), 'SCHED_FIFO': (1, 99)} lo, hi = ranges['SCHED_FIFO'] lo <= 50 <= hi
True
When to use
Use it
- Sizing worker pools by the CPUs actually available (Linux, before 3.13)
- Pinning latency-sensitive work to dedicated cores
- Real-time or idle-only scheduling of a process on Linux
Reach for something else
- Usable CPU count on 3.13+ → os.process_cpu_count() (portable)
- Simple "be nicer" → os.nice()
- Windows affinity → the third-party psutil (Process.cpu_affinity)
Notes
CPython impl
Wrappers of the sched_* system calls; sched_param is an immutable struct sequence (setting sched_priority raises AttributeError: readonly attribute)
Availability
Only on some Unix platforms (docs: "Interface to the scheduler"). All of these exist on Linux; none on Windows. SCHED_SPORADIC also exists on systems that support it
Linux values
SCHED_OTHER 0, SCHED_FIFO 1, SCHED_RR 2, SCHED_BATCH 3, SCHED_IDLE 5, SCHED_RESET_ON_FORK 0x40000000. Priority range: FIFO and RR 1..99, OTHER 0..0
Permissions
Switching to SCHED_FIFO / SCHED_RR raises PermissionError without root or CAP_SYS_NICE (checked on Linux)
Return types
sched_getaffinity: set; sched_getscheduler: int; sched_getparam: sched_param; sched_rr_get_interval: float seconds; sched_yield and the setters: None
FAQ
The scheduler functions exist only on some Unix platforms (Linux has them, Windows does not), and changing affinity or policy affects the whole process. The examples show the mask and policy arithmetic with the Linux values instead.