skip to content

What does os.nice() change about a Python process, and what can it not do?

level: middleimportance: nice to knowfreq 12%

answer

  1. Higher means less favoured, not more
  2. It adds an increment, never sets
  3. Only matters when something else wants the CPU
  4. Going down the scale needs privilege

basics

~20 s

os.nice(increment) adds to the process's niceness on Unix and returns the new value, biasing how the scheduler shares contended CPU time. It grants no extra CPU, cannot exceed a control-group quota, and needs privilege to go negative.

solid answer

~40 s

`os.nice(increment)` is a thin wrapper over the Unix niceness setting: it adds `increment` to the current value and returns the result, where higher means *less* favoured, in a range of roughly -20 to 19. It is a relative weighting used only when runnable work is competing for a processor — it changes how a fixed amount of CPU time is divided, never how much of it exists. So it cannot lift a control-group CPU quota, cannot add processors, and does nothing at all on an idle machine. Lowering the value (a negative increment) raises priority and requires privilege; an unprivileged process gets `PermissionError`. Children inherit the value, which makes it a cheap way to keep a batch pool out of the way of latency-sensitive work on a shared host.

code

python · 5 lines
python
import os

current = os.nice(0)
lowered = os.nice(5)
print(current, lowered)

go deeper

for a junior

Remember the direction of the scale: a higher niceness means the process is treated as less important. Reading the current value is os.nice(0), because the argument is an increment.

for a middle

Explain that it is a relative adjustment that only matters under contention, that negative increments need privilege and raise PermissionError otherwise, and that children inherit whatever value the parent had.

for a senior

Know its limits before reaching for it in an incident: it cannot lift a CPU quota, cannot add processors, and provides no isolation. Use it for co-tenant batch work on a host you own, and nothing stronger.

for a principal

Judge when a scheduling hint is the wrong instrument entirely — if the requirement is guaranteed service for one workload, that is a kernel-enforced resource decision, not a politeness setting that any co-tenant can ignore.

### What niceness is Every process on a Unix system carries a *niceness*: an integer, conventionally between -20 and 19, that biases the scheduler's decision about how much processor time to hand it when several runnable tasks are competing. The name reads backwards to most people on first contact — a **high** niceness means the process is being nice to others and gets *less* CPU; a **low** or negative value means it is favoured. The default is 0. `os.nice(increment)` adjusts that value **relatively**: it adds `increment` to the current niceness and returns the new value. It is not a setter, which is the first thing people get wrong — calling `os.nice(5)` twice leaves the process at 10, not 5. Calling `os.nice(0)` is the idiomatic way to read the current value without changing it. The function is Unix-only; on platforms without the underlying call it is simply absent from the `os` module. ### What it actually buys Niceness is a *share* control, and only under contention. When several runnable tasks want the same processor, the scheduler uses their niceness to weight how the available time is divided; each step is a meaningful multiplier, so a job at niceness 10 gets a small fraction of the time a job at 0 gets when the two compete. When nothing is competing, niceness has no observable effect whatsoever — a lone niced process on an idle core runs at full speed. That single sentence resolves most of the confusion around it. Niceness never creates CPU time; it only decides who gets the time that exists. ### What it cannot do The important negatives, in the order they come up in real incidents: - **It does not raise a control-group CPU quota.** A quota caps how much CPU time the whole group may consume per enforcement period. Niceness affects the split *inside* that allowance; when the allowance is spent, everything in the group is stopped regardless of how favoured it is. A process that is being throttled cannot nice its way out. - **It does not add processors.** Niceness is orthogonal to how many CPUs the process may run on; that is the affinity mask's job, and it is what makes `os.process_cpu_count()` differ from `os.cpu_count()`. - **It cannot usually be lowered.** Raising priority — a negative increment — is a privileged operation. An ordinary process attempting it gets a `PermissionError`, which is an `OSError` subclass, so the classic mistake of "we will just renice ourselves up when we detect load" fails in production and works when someone tests it as root. - **It is effectively one-way for an unprivileged process.** Having raised its niceness, an unprivileged process cannot bring it back down again, since that too is a decrease. ### Where it is genuinely useful The honest use case is *co-tenancy on a machine you control*. A batch job, a periodic re-index, a log compaction pass or a report generator that shares a host with latency-sensitive work can raise its own niceness at startup and stop stealing responsiveness from the foreground service when both are busy. Because children inherit the value, doing it once in a parent before spawning a pool covers every worker. It is a poor tool for anything else. It cannot enforce isolation — a niced process still competes, just less successfully — and it is worthless as a capacity mechanism, since the total CPU is unchanged. Where genuine isolation is required, the answer is a resource limit enforced by the kernel, not a scheduling hint. ### Two details worth knowing First, the value is inherited across process creation but *not* reset by an exec, so a niced parent produces niced children indefinitely — occasionally a surprise when a service is started from a niced shell and nobody can work out why it is slow under load. Second, on Linux the scheduling attributes the call manipulates are per-thread, despite the process-shaped name, so a niced worker thread does not automatically nice the rest of the interpreter. For the common pattern of nicing the whole program at startup, before any additional threads exist, that distinction does not bite — but it explains why nicing from inside one worker thread produces less effect than expected.

  • Why does os.nice(-5) fail for an ordinary process, and what exception surfaces?
    Lowering the niceness value asks the scheduler to favour you over everyone else, so it is a privileged operation; an unprivileged caller gets `PermissionError`, a subclass of `OSError`. That asymmetry is deliberate — any process may volunteer to be less important, none may promote itself. It also means an unprivileged process that has raised its niceness cannot undo it, since the reversal is itself a decrease.
  • If a container is being CPU-throttled, can lowering the niceness of the busiest process help?
    No. Throttling means the whole control group has spent its CPU time allowance for the period and every thread in it is stopped until the next period. Niceness only weights how the allowance is divided among competing tasks inside the group, so it can shift which work gets served first but cannot increase the total. The fix is fewer workers or a larger grant, not a scheduling hint.
  • How does niceness interact with worker processes started from a pool?
    Children inherit the parent's niceness, so raising it once before creating the pool applies to every worker without touching worker code. That makes it a tidy way to keep a batch pool out of the way of a latency-sensitive process on the same host. The inheritance also cuts the other way: a service accidentally launched from an already-niced shell quietly runs its whole pool at reduced priority.

It is a place in the queue, not a bigger portion: being polite gets you served after everyone else, but the kitchen still cooks exactly as much food as before.

saying these in an interview costs you the question

  • Thinks a higher niceness means higher priority
  • Treats os.nice() as setting an absolute value
  • Expects nicing to escape a control-group CPU quota
  • Believes any process can nice itself upward
  • Says niceness matters on an otherwise idle machine

context