ZetCode

Python os.set_inheritable 函数

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

这份全面的指南探讨了 Python 的 os.set_inheritable 函数,该函数控制跨进程创建的文件描述符继承。我们将涵盖继承标志、进程管理和实际示例。

基本定义

os.set_inheritable 函数设置文件描述符的继承标志。这决定了子进程是否可以继承该描述符。

关键参数:fd(文件描述符),inheritable(布尔标志)。 返回 None。 在具有不同底层实现的 Unix 和 Windows 系统上可用。

基本用法示例

此示例演示了在生成子进程之前将文件描述符设置为可继承。子进程将继承打开的文件。

basic_inheritance.py
import os

# Create a temporary file
fd = os.open("test.txt", os.O_RDWR | os.O_CREAT)

# Make the file descriptor inheritable
os.set_inheritable(fd, True)

# Spawn a child process
pid = os.fork()

if pid == 0:  # Child process
    print(f"Child process with PID {os.getpid()}")
    os.write(fd, b"Written by child\n")
    os.close(fd)
else:  # Parent process
    print(f"Parent process with PID {os.getpid()}")
    os.waitpid(pid, 0)  # Wait for child
    os.lseek(fd, 0, os.SEEK_SET)
    print("File content:", os.read(fd, 100))
    os.close(fd)
    os.unlink("test.txt")

父进程创建一个文件并在分叉之前将其设置为可继承。 然后,两个进程都可以写入同一个文件描述符。

这演示了父进程和子进程之间的基本继承行为。

阻止继承

此示例展示了如何防止文件描述符被子进程继承。 这对于安全敏感的文件操作很有用。

prevent_inheritance.py
import os

# Open a sensitive file
fd = os.open("secret.txt", os.O_RDONLY)

# Explicitly prevent inheritance
os.set_inheritable(fd, False)

# Spawn child process
pid = os.fork()

if pid == 0:  # Child process
    try:
        # Attempt to read from the file
        print(os.read(fd, 100))
    except OSError as e:
        print(f"Child failed to access file: {e}")
    finally:
        os._exit(0)
else:  # Parent process
    os.waitpid(pid, 0)
    print("Parent can still read:", os.read(fd, 100))
    os.close(fd)

父进程打开一个文件但阻止继承。 子进程无法访问文件描述符,而父进程保留访问权限。

此技术有助于保护敏感资源免受子进程的访问。

使用管道的继承

此示例演示了管道文件描述符的继承行为,这些文件描述符通常用于进程间通信。

pipe_inheritance.py
import os

# Create a pipe
r, w = os.pipe()

# Set read end as inheritable
os.set_inheritable(r, True)

pid = os.fork()

if pid == 0:  # Child process
    os.close(w)  # Close write end
    print("Child received:", os.read(r, 100))
    os.close(r)
else:  # Parent process
    os.close(r)  # Close read end
    os.write(w, b"Message from parent")
    os.close(w)
    os.waitpid(pid, 0)

父进程创建一个管道并将读取端设置为可继承。 子进程继承读取描述符,可以从父进程接收数据。

管道是受控描述符继承的常见用例。

检查继承状态

此示例展示了如何使用 os.get_inheritable 检查文件描述符的当前继承状态。

check_inheritance.py
import os

fd = os.open("temp.txt", os.O_RDWR | os.O_CREAT)

# Check default inheritance status
print("Default inheritable:", os.get_inheritable(fd))

# Change and verify status
os.set_inheritable(fd, True)
print("After setting True:", os.get_inheritable(fd))

os.set_inheritable(fd, False)
print("After setting False:", os.get_inheritable(fd))

os.close(fd)
os.unlink("temp.txt")

该代码打开一个文件并检查其默认继承状态。 然后它修改并验证状态更改。

这演示了如何动态检查和修改继承标志。

与子进程的继承

此示例展示了文件描述符继承如何与 Python 的 subprocess 模块一起工作。

subprocess_inheritance.py
import os
import subprocess

# Create a file and make inheritable
fd = os.open("output.txt", os.O_RDWR | os.O_CREAT)
os.set_inheritable(fd, True)

# Launch subprocess with inherited descriptor
proc = subprocess.Popen(
    ["python3", "-c", f"import os; os.write({fd}, b'Written by subprocess\\n')"],
    pass_fds=[fd]
)

proc.wait()

# Verify content
os.lseek(fd, 0, os.SEEK_SET)
print("File content:", os.read(fd, 100))
os.close(fd)
os.unlink("output.txt")

父进程打开一个文件并显式地将其传递给一个子进程。 子进程继承该描述符并写入该文件。

这演示了使用 Python 的更高级别进程 API 进行的受控继承。

Windows 特定的行为

此示例重点介绍了 set_inheritable 的 Windows 特有行为,其中继承的工作方式与 Unix 系统不同。

windows_inheritance.py
import os
import sys

if sys.platform != "win32":
    print("This example is for Windows only")
    sys.exit(1)

# On Windows, inheritance must be set at creation time
import msvcrt

fd = os.open("winfile.txt", os.O_RDWR | os.O_CREAT)

# Windows requires setting inheritable flag at creation
handle = msvcrt.get_osfhandle(fd)
print(f"Original handle inheritable: {msvcrt.HANDLE(handle).inheritable}")

# Try to modify inheritance (may not work as expected)
os.set_inheritable(fd, True)
print(f"After set_inheritable: {msvcrt.HANDLE(handle).inheritable}")

os.close(fd)
os.unlink("winfile.txt")

在 Windows 上,继承标志通常在句柄创建时设置。 与 Unix 系统相比,set_inheritable 的效果可能有限。

这演示了描述符继承中的重要平台差异。

安全注意事项

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程