Python添加suffix创建临时文件后打开提示文件被占用错误
问题分析:临时文件被占用导致无法访问的错误
问题情况
运行指定Python代码时,若为临时文件指定后缀(如.xlsx),会抛出错误:
The process cannot access the file because it is being used by another process.
移除suffix参数后无报错,但文件无法通过默认关联程序(如Excel)正常打开。
运行代码
import os import tempfile import subprocess def os_read_binary_file(binary_data, original_file_name=None): suffix = None if original_file_name: suffix = os.path.splitext(original_file_name)[1] with tempfile.NamedTemporaryFile(mode="wb", suffix=suffix) as f: f.write(binary_data) f.flush() file_path = f.name p = subprocess.check_output(["start", file_path], shell=True) def read_file_to_bolb(filename): with open(filename, 'rb') as file: bolb_data = file.read() return bolb_data bin = read_file_to_bolb('./zxc.xlsx') os_read_binary_file(bin, 'zxc.xlsx')
错误信息
The process cannot access the file because it is being used by another process.
运行环境
- Windows 10
- Python 3.8.10
原因解析
- Windows文件锁定机制:Python的
tempfile.NamedTemporaryFile在Windows系统下,默认以独占写入模式创建临时文件,Python进程会一直持有文件句柄,直到with代码块执行完毕。 - 关联程序的独占需求:当指定
.xlsx后缀时,start命令会调用Excel打开文件。而Excel打开xlsx格式文件时,会尝试获取文件的独占访问权限,但此时文件仍被Python进程锁定,因此触发“文件被占用”的错误。 - 无后缀时的特殊情况:移除
suffix后,临时文件无扩展名,start会调用系统默认的无扩展名文件打开程序(通常是记事本)。记事本打开文件时不会请求独占锁定,因此不会报错,但也无法用Excel正常解析文件内容。
解决方案
要解决这个问题,核心是确保在启动外部程序打开临时文件前,Python进程已经释放文件句柄。可以通过以下两种方式实现:
方式1:使用临时目录创建文件
创建临时目录,在目录内生成目标文件并关闭句柄后,再启动外部程序:
import os import tempfile import subprocess def os_read_binary_file(binary_data, original_file_name=None): suffix = '' if original_file_name: suffix = os.path.splitext(original_file_name)[1] # 创建临时目录,with块结束后自动删除目录及内容 with tempfile.TemporaryDirectory() as temp_dir: file_path = os.path.join(temp_dir, f"temp_file{suffix}") with open(file_path, 'wb') as f: f.write(binary_data) # 文件已关闭,句柄释放,启动外部程序 subprocess.run(["start", "", file_path], shell=True) def read_file_to_bolb(filename): with open(filename, 'rb') as file: return file.read() bin_data = read_file_to_bolb('./zxc.xlsx') os_read_binary_file(bin_data, 'zxc.xlsx')
方式2:创建非自动删除的临时文件
使用delete=False创建临时文件,手动关闭句柄后启动程序,最后手动删除文件:
import os import tempfile import subprocess import time def os_read_binary_file(binary_data, original_file_name=None): suffix = None temp_file = None try: if original_file_name: suffix = os.path.splitext(original_file_name)[1] # 创建临时文件,指定delete=False避免自动删除 temp_file = tempfile.NamedTemporaryFile(mode="wb", suffix=suffix, delete=False) temp_file.write(binary_data) temp_file.flush() temp_file.close() # 手动关闭,释放文件句柄 # 启动外部程序打开文件 subprocess.run(["start", "", temp_file.name], shell=True) # 延迟一段时间,确保程序已打开文件后再删除(根据实际情况调整时长) time.sleep(2) finally: # 手动删除临时文件 if temp_file and os.path.exists(temp_file.name): os.unlink(temp_file.name) def read_file_to_bolb(filename): with open(filename, 'rb') as file: return file.read() bin_data = read_file_to_bolb('./zxc.xlsx') os_read_binary_file(bin_data, 'zxc.xlsx')
注意:
subprocess.run中添加空字符串是为了兼容Windows的start命令语法,避免文件名含空格时出现问题。
内容的提问来源于stack exchange,提问作者Over Drive Gain
相关产品推荐
相关产品推荐

