在Python中无需重写即可持久化TemporaryFile | 调用linkat
如何将O_TMPFILE创建的临时文件持久化(无需重写)
你可以通过ctypes直接调用Linux系统的linkat()系统调用来实现,无需编译C扩展。以下是可行的代码示例:
import tempfile import os import ctypes from ctypes import c_int, c_char_p # 定义系统调用所需的常量 AT_FDCWD = -100 AT_EMPTY_PATH = 0x1000 # 加载系统libc库 libc = ctypes.CDLL(None) # 声明linkat函数的参数类型,确保调用时参数格式正确 libc.linkat.argtypes = [c_int, c_char_p, c_int, c_char_p, c_int] libc.linkat.restype = c_int # 模拟Starlette生成的TemporaryFile(需保证临时文件目录和目标路径在同一文件系统) tempfile.tempdir = "/home/user/tmp" with tempfile.TemporaryFile() as fp: # 写入测试内容 fp.write(b"Das ist ein Test") # 获取临时文件的文件描述符 fd = fp.raw.fileno() # 目标路径需编码为字节串 target_path = "/home/user/tmp/test.txt".encode('utf-8') # 调用linkat完成持久化:利用AT_EMPTY_PATH标识通过文件描述符定位源文件 ret = libc.linkat(fd, b"", AT_FDCWD, target_path, AT_EMPTY_PATH) if ret != 0: # 获取错误信息并抛出异常 errno = ctypes.get_errno() raise OSError(errno, os.strerror(errno))
关键说明
- 常量作用:
AT_FDCWD表示以当前工作目录为基准解析目标路径,AT_EMPTY_PATH告知系统调用通过第一个参数的文件描述符而非路径字符串定位源文件。 - 文件系统限制:临时文件和目标路径必须处于同一块设备/文件系统(硬链接的特性要求),否则会调用失败。
- 错误处理:
linkat()返回非0值表示调用失败,可通过ctypes.get_errno()获取具体错误码,转换为Python标准的OSError抛出。
之前尝试失败的原因
Python标准库的os.link()仅支持路径字符串作为源参数,不直接兼容文件描述符,无法处理O_TMPFILE类型的无路径临时文件,因此必须直接调用底层系统调用完成操作。
内容的提问来源于stack exchange,提问作者Kound
相关产品推荐
相关产品推荐

