ZetCode

Python os.setpriority 函数

上次修改时间:2025 年 4 月 11 日

这份全面的指南探讨了 Python 的 os.setpriority 函数,该函数用于调整进程调度优先级。我们将涵盖优先级级别、nice 值、进程选择以及进程管理的实际示例。

基本定义

os.setpriority 函数设置进程、进程组或用户的调度优先级。它在类 Unix 系统上可用,并影响 CPU 调度。

关键参数:which (PRIO_PROCESS, PRIO_PGRP, PRIO_USER), who (进程 ID), priority (nice 值,范围从 -20 到 19)。较低的值意味着较高的优先级。

设置当前进程优先级

os.setpriority 最简单的用法是调整当前进程的优先级。此示例演示了设置不同的 nice 值。

current_process.py
import os
import time

# Get current priority
current_nice = os.getpriority(os.PRIO_PROCESS, os.getpid())
print(f"Current nice value: {current_nice}")

# Set higher priority (lower nice value)
os.setpriority(os.PRIO_PROCESS, os.getpid(), -10)
print(f"New nice value: {os.getpriority(os.PRIO_PROCESS, os.getpid())}")

# CPU-intensive task
start = time.time()
for _ in range(10**7):
    pass
print(f"Execution time: {time.time() - start:.2f} seconds")

# Reset to default priority
os.setpriority(os.PRIO_PROCESS, os.getpid(), 0)

此示例首先获取当前 nice 值,然后提高优先级。请注意,设置负值通常需要超级用户权限。

CPU 密集型任务可能会以更高的优先级运行得更快,但结果会因系统负载和调度程序实现而异。

设置子进程优先级

您可以在创建后设置子进程的优先级。此示例派生一个子进程并独立于父进程调整其优先级。

child_process.py
import os
import time

def worker():
    print(f"Child PID: {os.getpid()}")
    start = time.time()
    for _ in range(10**7):
        pass
    print(f"Child execution time: {time.time() - start:.2f}")

pid = os.fork()
if pid == 0:  # Child process
    worker()
else:  # Parent process
    # Set child to lower priority (higher nice value)
    os.setpriority(os.PRIO_PROCESS, pid, 10)
    print(f"Set child {pid} to nice value 10")
    
    # Parent continues with default priority
    start = time.time()
    for _ in range(10**7):
        pass
    print(f"Parent execution time: {time.time() - start:.2f}")

父进程将子进程设置为较低的优先级(nice 值 10),同时保持自身的正常优先级。这可能会导致父进程首先完成。

请注意,fork() 是 Unix 特有的。在 Windows 上,请改用 multiprocessing。

设置进程组优先级

os.setpriority 可以调整整个进程组的优先级。这会影响组中的所有进程,适用于批量操作。

process_group.py
import os
import time

# Create new process group
os.setpgid(0, 0)
pgid = os.getpgid(0)

print(f"Process group ID: {pgid}")

# Set priority for entire group
os.setpriority(os.PRIO_PGRP, pgid, 5)

# Verify setting
print(f"Group nice value: {os.getpriority(os.PRIO_PGRP, pgid)}")

# Child processes inherit group priority
for _ in range(3):
    pid = os.fork()
    if pid == 0:
        print(f"Child {os.getpid()} nice: {os.getpriority(os.PRIO_PROCESS, 0)}")
        time.sleep(1)
        os._exit(0)

# Wait for children
for _ in range(3):
    os.wait()

这将创建一个新的进程组并设置其优先级。子进程会自动继承该组的优先级设置。

当您需要将多个相关进程作为一个单元进行管理时,进程组非常有用。

设置用户进程优先级

PRIO_USER 选项设置用户拥有的所有进程的优先级。这需要超级用户权限,并影响所有当前和未来的进程。

user_priority.py
import os
import pwd

try:
    # Get user ID for 'nobody'
    user_id = pwd.getpwnam('nobody').pw_uid
    
    # Set priority for all user's processes
    os.setpriority(os.PRIO_USER, user_id, 10)
    print(f"Set nice value 10 for user nobody")
    
    # Verify setting
    current = os.getpriority(os.PRIO_USER, user_id)
    print(f"Current nice value for user: {current}")
    
except PermissionError:
    print("Error: Requires superuser privileges")
except KeyError:
    print("Error: User nobody not found")

这尝试为 'nobody' 用户拥有的所有进程设置较低的优先级。请注意,这需要 root 权限,并影响所有用户的进程。

请谨慎使用此功能,因为它可能会严重影响受影响用户的系统性能。

处理权限错误

设置高优先级(负 nice 值)通常需要提升的权限。此示例演示了正确的错误处理。

permission_handling.py
import os
import sys

def set_high_priority():
    try:
        os.setpriority(os.PRIO_PROCESS, 0, -10)
        print("Successfully set high priority")
    except PermissionError:
        print("Permission denied: need superuser privileges")
        # Fall back to maximum allowed priority
        min_nice = os.getpriority(os.PRIO_PROCESS, 0)
        if min_nice > 0:
            os.setpriority(os.PRIO_PROCESS, 0, 0)
            print("Set to default priority instead")
        else:
            os.setpriority(os.PRIO_PROCESS, 0, min_nice)
            print(f"Set to minimum allowed nice value: {min_nice}")

if __name__ == "__main__":
    set_high_priority()

这尝试设置高优先级,如果权限被拒绝,则回退到允许的最佳优先级。该方法优雅地降低了功能。

在处理进程优先级时,始终处理权限错误,因为可用性取决于用户权限。

跨平台注意事项

进程优先级处理在不同平台之间有所不同。此示例演示了一种使用 try/except 的跨平台兼容方法。

cross_platform.py
import os
import sys
import platform

def set_low_priority():
    """Set process to low priority, works across platforms"""
    system = platform.system()
    
    try:
        if system == "Windows":
            import win32api
            import win32process
            import win32con
            
            pid = win32api.GetCurrentProcessId()
            handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid)
            win32process.SetPriorityClass(handle, win32process.BELOW_NORMAL_PRIORITY_CLASS)
        else:  # Unix-like
            os.setpriority(os.PRIO_PROCESS, 0, 10)  # Low priority
            
        print("Successfully set low priority")
    except Exception as e:
        print(f"Failed to set priority: {str(e)}")

if __name__ == "__main__":
    set_low_priority()

这将检查操作系统并使用适当的方法来设置进程优先级。Windows 需要 pywin32 才能实现类似的功能。

该示例展示了如何在不同平台上维护功能,同时优雅地处理潜在的错误。

优先级和 CPU 亲和性

将优先级设置与 CPU 亲和性相结合可以优化性能。此示例演示了 Linux 上的这两种技术。

priority_affinity.py
import os
import time

def set_cpu_affinity(cpus):
    """Set CPU affinity mask (Linux only)"""
    mask = 0
    for cpu in cpus:
        mask |= 1 << cpu
    os.sched_setaffinity(0, [mask])

try:
    # Set high priority
    os.setpriority(os.PRIO_PROCESS, 0, -5)
    
    # Restrict to CPU 0
    set_cpu_affinity([0])
    
    # Performance test
    start = time.time()
    for _ in range(10**7):
        pass
    duration = time.time() - start
    
    print(f"Execution time: {duration:.2f} seconds")
    
except PermissionError:
    print("Need root privileges for high priority setting")
except AttributeError:
    print("CPU affinity not supported on this platform")

这将高优先级与 CPU 亲和性相结合,以潜在地提高 CPU 密集型任务的性能。这两种操作都可能需要特殊权限。

CPU 亲和性将进程限制为特定核心,而优先级影响在这些核心内的调度。

安全注意事项

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程