You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中os.copy_file_range搭配O_APPEND报错:Bad file descriptor问题

问题原因

os.copy_file_range 底层调用的是Linux内核的copy_file_range()系统调用,该调用不允许目标文件描述符以O_APPEND模式打开。

原因在于:O_APPEND模式会强制内核将所有写入操作的偏移量自动设置为文件末尾,但copy_file_range是基于显式偏移量实现高效块级复制的,当目标fd带有O_APPEND标记时,内核会判定该fd不符合操作要求,返回EBADF(错误号9,对应"Bad file descriptor")。

你提到os.write在O_APPEND模式下能正常工作,是因为write()系统调用本身兼容O_APPEND模式——内核会自动调整偏移量后执行写入,但copy_file_range的设计逻辑不支持这种自动调整。

高效解决办法

要保持copy_file_range的高效性同时实现追加复制,可通过手动指定目标文件的偏移量替代O_APPEND模式,具体步骤如下:

  1. 获取目标文件的当前大小(作为追加的起始偏移量)
  2. 以普通只写模式打开目标文件(无需O_APPEND)
  3. 调用copy_file_range时显式传入目标偏移量参数

示例代码:

import os

from_path = "source.txt"
to_path = "target.txt"

# 获取目标文件当前大小,作为追加起始位置
try:
    target_offset = os.path.getsize(to_path)
except FileNotFoundError:
    target_offset = 0

fd_from = os.open(from_path, os.O_RDONLY)
# 用O_WRONLY | O_CREAT确保文件存在(若需保留原有权限,可添加mode参数,比如0o644)
fd_to = os.open(to_path, os.O_WRONLY | os.O_CREAT)

# 显式指定目标偏移量,实现追加效果
os.copy_file_range(fd_from, fd_to, os.path.getsize(from_path), dst_offset=target_offset)

os.close(fd_from)
os.close(fd_to)

这个方法完全复用copy_file_range的高效块复制能力,效率和你之前正常运行的版本一致,同时满足追加到目标文件末尾的需求。

补充说明

你提到此前类似代码可正常运行,大概率是因为当时目标文件并未以O_APPEND模式打开,或者使用了更低版本的内核(部分旧内核对copy_file_range的参数限制更宽松,但5.15版本的内核已明确禁止O_APPEND的目标fd)。

内容的提问来源于stack exchange,提问作者Calhau18

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 03:45:52