使用with语句后无法删除文件,疑子进程占用文件资源
问题描述
我用Python开发自动评分程序,需要将学生Java作业的程序输出写入临时txt文件。通过with语句成功写入文件后,执行os.remove(file.txt)删除文件时,持续出现以下错误:
PermissionError: [WinError 32] 该文件正被另一进程占用,无法访问: 'file.txt'
我猜测是with语句未正确关闭文件,尝试添加file.close()但无作用(我知道这有些多余)。也怀疑问题出在subprocess.Popen()语句,但之前在其他程序中使用该语句操作同一文件时并未出现问题。尝试用kill()终止子进程,但未能成功实现。
相关代码如下:
hw_file = f"{submissions_folder}\\TaylorDavisOnTime.java" # example of naming style for student assignments student_txt_file = hw_file.replace(f"{submissions_folder}\\", f"{submissions_folder}\\output\\").replace(".java", "Output.txt") with open(student_txt_file, "w") as file: output = subprocess.Popen(["java", hw_file], stdin=subprocess.PIPE, stdout=file, text=True) for input in input_values: output.stdin.write(input[0]) output.stdin.write(str(input[1])) output.stdin.write(str(input[2])) output.stdin.flush() output.stdin.close() # output.kill() # still playing with this remove = True file.close() # redundant, but does nothing if remove: os.remove(student_txt_file)
问题分析与解决方向
- 核心原因:你启动的Java子进程仍在运行,它的标准输出流还占用着目标txt文件,导致Python进程无法删除该文件。with语句确实已关闭
file句柄,但子进程未结束时,操作系统会判定文件处于占用状态。 - 具体解决步骤:
- 等待子进程完全退出:在关闭标准输入后,调用
output.wait()等待Java程序执行完毕并退出,确保它释放对输出文件的占用。这是解决文件占用问题的关键。 - 修正输入传递格式:当前的输入写法可能不符合Java程序的预期(比如缺少换行符),导致Java程序一直等待输入,无法正常结束。要根据Java程序的输入要求调整,例如每个输入项后添加
\n,确保程序能接收完所有输入并执行完成。 - 移除冗余的文件关闭操作:with语句会自动管理文件生命周期,手动调用
file.close()完全没必要,应删除该代码。 - 可选优化:避免临时文件:如果评分逻辑不需要持久化输出文件,可直接通过
subprocess.communicate()获取Java程序的输出内容,无需写入文件,从根源上避免文件占用问题。
- 等待子进程完全退出:在关闭标准输入后,调用
修改后的示例代码:
hw_file = f"{submissions_folder}\\TaylorDavisOnTime.java" student_txt_file = hw_file.replace(f"{submissions_folder}\\", f"{submissions_folder}\\output\\").replace(".java", "Output.txt") with open(student_txt_file, "w") as file: output = subprocess.Popen(["java", hw_file], stdin=subprocess.PIPE, stdout=file, text=True) # 按Java程序预期格式传递输入,添加换行符 for input in input_values: output.stdin.write(f"{input[0]}\n{str(input[1])}\n{str(input[2])}\n") output.stdin.flush() output.stdin.close() # 等待子进程执行完毕 output.wait() remove = True if remove: os.remove(student_txt_file)
内容的提问来源于stack exchange,提问作者NeverEndingQuestions
相关产品推荐
相关产品推荐

