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 教程。