os.cpu_count

cpu_count() counts the logical CPUs of the machine; process_cpu_count() (new in 3.13) counts the ones this process may actually run on, which can be fewer under CPU affinity. Both can return None. getloadavg() is Unix only; times() works on Unix and Windows, but on Windows only user and system are filled in.

os functionPython 3.4+ (process_cpu_count 3.13+)
Common call
workers = os.process_cpu_count() or 1
Returns
int, or None when undetermined
Replaces
multiprocessing.cpu_count() (which raises instead of returning None)
Watch out
None is a possible result: always add "or 1"
os.cpu_count() / os.process_cpu_count() / os.getloadavg() / os.times()
→ int | None

Common patterns

Pool size that works on 3.12 and 3.13
Prefer the usable-CPU count; fall back to the machine count; never None.
import os
count = getattr(os, 'process_cpu_count', os.cpu_count)() or 1
workers = max(1, count - 1)
Usable CPUs before 3.13 on Linux
sched_getaffinity(0) is the set of CPUs this process may run on.
import os
usable = len(os.sched_getaffinity(0))
Load average per CPU (Unix)
A 1-minute load above the CPU count means work is queueing.
import os
one, five, fifteen = os.getloadavg()
busy = one / (os.cpu_count() or 1) > 1.0
CPU time spent by a block
user + system is CPU time; elapsed is wall-clock time.
import os
t0 = os.times()
work()
t1 = os.times()
cpu = (t1.user - t0.user) + (t1.system - t0.system)
wall = t1.elapsed - t0.elapsed

Examples

1. An int or None, never 0
import os c = os.cpu_count() c is None or (isinstance(c, int) and c >= 1)
Returns
True
2. 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
True
3. times() is a 5-field struct sequence
import os t = os.times() (type(t).__name__, len(t), os.times_result.n_fields)
Returns
('times_result', 5, 5)
4. Fields by name or by position
import os t = os.times() t.user == t[0] and t.elapsed == t[4]
Returns
True
5. Building a times_result by hand
import os t = os.times_result((1.5, 0.25, 0.0, 0.0, 100.0)) t.user + t.system
Returns
1.75
6. elapsed only moves forward
import os t0 = os.times() sum(i * i for i in range(100000)) t1 = os.times() t1.elapsed >= t0.elapsed
Returns
True
7. getloadavg exists only on Unix
import os hasattr(os, 'getloadavg') == (os.name == 'posix')
Returns
True

Pitfalls

1. Doing arithmetic on a None CPU count
cpu_count() returns None when the count is undetermined. The typical "cores minus one" line then crashes; "or 1" makes it safe.
count - 1
count = None  # what os.cpu_count() returns when undetermined
count - 1
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
(count or 1)
count = None
max(1, (count or 1) - 1)
1
2. Sizing a pool by the machine instead of the process
In a container or under taskset the process may be limited to a few CPUs while cpu_count() still reports all of them. Ask for the usable set.
cpu_count()
import os
isinstance(os.cpu_count(), int)
True
usable CPUs
import os
usable = (getattr(os, 'process_cpu_count', None) or os.cpu_count)()
usable <= os.cpu_count()
True

When to use

Use it
  • Choosing a default worker count for a thread or process pool
  • Measuring CPU time (user + system) of your own process with times()
  • Quick load checks on Unix servers with getloadavg()
Reach for something else
  • Timing code precisely → time.perf_counter() or time.process_time()
  • Per-process CPU and memory of other processes → the third-party psutil package

Notes

CPython impl
cpu_count and process_cpu_count honour the -X cpu_count=n option and the PYTHON_CPU_COUNT environment variable (3.13+), which override the detected value
Availability
cpu_count, times: Unix, Windows. getloadavg: Unix only (raises OSError if the load average is unobtainable). process_cpu_count: added in 3.13, not listed in os.__all__
Windows times()
Only user and system are known; children_user, children_system and elapsed are 0
times_result
A tuple-like struct sequence: user, system, children_user, children_system, elapsed (named attributes since 3.3)

FAQ

CPU counts, load averages and CPU times are properties of the machine running the code, so they differ for every reader. The examples check types and relations that hold everywhere. getloadavg is Unix only and does not exist on Windows.