Python os.write 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨 Python 的 os.write 函数,该函数使用文件描述符执行底层文件写入。我们将介绍文件描述符、字节字符串、返回值和实际示例。
基本定义
os.write 函数将字节写入文件描述符。 它是一种绕过 Python 文件对象层的底层操作。
主要参数:fd(文件描述符),data(类字节对象)。 返回实际写入的字节数。 需要正确的文件打开和权限。
基本文件写入
此示例演示了使用 os.write 将数据写入文件的最简单方法。 我们首先打开文件以获取文件描述符。
import os
# Open file and get file descriptor
fd = os.open("output.txt", os.O_WRONLY | os.O_CREAT)
# Write bytes to file
data = b"Hello, World!\n"
bytes_written = os.write(fd, data)
print(f"Wrote {bytes_written} bytes")
# Close file descriptor
os.close(fd)
该代码以只写访问模式打开文件,如果需要则创建文件,写入字节,然后关闭描述符。 注意字节字面量的前缀 'b'。
始终关闭文件描述符以防止资源泄漏。 返回值显示实际写入了多少字节。
写入多个块
可以多次调用 os.write 以分块写入数据。 此示例显示了对同一文件描述符的顺序写入。
import os
fd = os.open("log.txt", os.O_WRONLY | os.O_CREAT | os.O_APPEND)
messages = [
b"System started\n",
b"Loading modules...\n",
b"Initialization complete\n"
]
for msg in messages:
bytes_written = os.write(fd, msg)
print(f"Wrote {bytes_written} bytes")
os.close(fd)
我们以追加模式打开文件以保留现有内容。 每个字符串都是单独写入的,并在每次写入后报告进度。
O_APPEND 标志确保写入操作转到文件末尾,即使其他进程同时写入该文件也是如此。
处理大型文件
对于大型文件,以固定大小的块写入数据是高效的。 此示例演示了以较小的片段写入大型字节数组。
import os
# Generate 1MB of data
data = b"X" * (1024 * 1024)
fd = os.open("large_file.bin", os.O_WRONLY | os.O_CREAT)
chunk_size = 4096 # 4KB chunks
total_written = 0
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
written = os.write(fd, chunk)
total_written += written
print(f"Written {total_written} bytes", end="\r")
os.close(fd)
print(f"\nTotal written: {total_written} bytes")
该代码以 4KB 的块写入 1MB 的文件。 这种方法节省内存,并在操作期间提供进度反馈。
注意 print 中的回车符 (\r) 以更新同一行,从而创建进度指示器效果。
错误处理
os.write 可能会引发异常。 此示例显示了针对常见场景(如磁盘已满或权限问题)的正确错误处理。
import os
import errno
try:
fd = os.open("protected.txt", os.O_WRONLY | os.O_CREAT)
data = b"Attempting to write to protected file\n"
try:
bytes_written = os.write(fd, data)
print(f"Successfully wrote {bytes_written} bytes")
except OSError as e:
if e.errno == errno.ENOSPC:
print("Error: No space left on device")
elif e.errno == errno.EBADF:
print("Error: Bad file descriptor")
else:
print(f"Write error: {e}")
finally:
os.close(fd)
except PermissionError:
print("Error: Permission denied for file creation")
except OSError as e:
print(f"File open error: {e}")
该示例演示了嵌套的 try-except 块,以处理文件打开和写入阶段的不同错误场景。
特定的错误编号 (errno) 有助于识别确切的故障原因,以便进行适当的处理。
非阻塞 I/O
对于非阻塞文件描述符,os.write 可能会写入比请求的字节数更少的字节。 此示例显示了如何处理部分写入。
import os
import errno
# Create a named pipe (run this only once)
if not os.path.exists("mypipe"):
os.mkfifo("mypipe")
# Open in non-blocking mode
fd = os.open("mypipe", os.O_WRONLY | os.O_NONBLOCK)
data = b"X" * 65536 # Large chunk of data
total = len(data)
written = 0
try:
while written < total:
try:
n = os.write(fd, data[written:])
if n == 0:
print("Write would block")
break
written += n
print(f"Written {written}/{total} bytes")
except OSError as e:
if e.errno == errno.EAGAIN:
print("Resource temporarily unavailable")
break
raise
finally:
os.close(fd)
该代码演示了以非阻塞模式写入命名管道。 它处理部分写入和管道已满时发生的 EAGAIN 错误。
非阻塞 I/O 对于在执行 I/O 操作时必须保持响应的应用程序非常有用。
二进制数据写入
os.write 是写入二进制数据的理想选择。 此示例显示了如何使用 struct 模块写入结构化的二进制数据。
import os
import struct
fd = os.open("data.bin", os.O_WRONLY | os.O_CREAT)
# Pack different data types into bytes
points = [
struct.pack("ffi", 1.5, 2.5, 10), # x, y, color
struct.pack("ffi", 3.1, 4.2, 20),
struct.pack("ffi", 5.0, 6.0, 30)
]
for point in points:
os.write(fd, point)
os.close(fd)
print("Binary data written successfully")
该示例以二进制格式写入三个点(每个点包含两个浮点数和一个整数)。 struct.pack 将 Python 值转换为字节。
二进制文件写入在性能敏感的应用程序(如游戏或科学计算)中很常见。
标准输出写入
文件描述符 1 表示标准输出。 此示例显示了使用 os.write 直接写入 stdout。
import os
import sys
# Method 1: Using file descriptor 1
os.write(1, b"Writing to stdout via file descriptor\n")
# Method 2: Using sys.stdout's fileno()
stdout_fd = sys.stdout.fileno()
os.write(stdout_fd, b"Writing via sys.stdout's descriptor\n")
# Method 3: Using os.fdopen
with os.fdopen(1, "wb") as f:
f.write(b"Writing via fdopen wrapper\n")
该示例演示了三种写入 stdout 的方法。 第一种方法使用众所周知的描述符编号 (1),第二种方法使用 sys.stdout 的描述符。
当您需要绕过 Python 的缓冲或在较低级别工作时,直接 stdout 写入可能很有用。
安全注意事项
- 文件描述符: 必须正确打开和关闭
- 数据验证: 确保只写入预期的数据
- 错误处理: 始终检查返回值并处理错误
- 竞争条件: 文件状态可能会在操作之间发生变化
- 平台差异: 行为可能因操作系统而异
最佳实践
- 使用上下文管理器: 用于自动关闭描述符
- 检查返回值: 验证是否写入了所有字节
- 首选缓冲 I/O: 适用于大多数高级应用程序
- 处理部分写入: 尤其是在非阻塞模式下
- 清理资源: 始终关闭文件描述符
资料来源
作者
列出所有 Python 教程。