Streamlit应用中Python subprocess删除文件遇WinError 5权限拒绝
问题:Streamlit调用subprocess执行文件删除时出现WinError 5权限拒绝
错误信息
[WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\CO_concentration-2023-12-29.gif' Failed to delete C:\Users\ludov\Bureau\eco-tech-h2gam\forecast\fr\NO2_concentration-2023-12-29.gif. Reason: [WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\NO2_concentration-2023-12-29.gif' Failed to delete C:\Users\ludov\Bureau\eco-tech-h2gam\forecast\fr\O3_concentration-2023-12-29.gif. Reason: [WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\O3_concentration-2023-12-29.gif' Failed to delete C:\Users\ludov\Bureau\eco-tech-h2gam\forecast\fr\PM10_concentration-2023-12-29.gif. Reason: [WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\PM10_concentration-2023-12-29.gif' Failed to delete C:\Users\ludov\Bureau\eco-tech-h2gam\forecast\fr\PM2.5_concentration-2023-12-29.gif. Reason: [WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\PM2.5_concentration-2023-12-29.gif' Failed to delete C:\Users\ludov\Bureau\eco-tech-h2gam\forecast\fr\SO2_concentration-2023-12-29.gif. Reason: [WinError 5] Accès refusé: 'C:\\Users\\ludov\\Bureau\\eco-tech-h2gam\\forecast\\fr\\SO2_concentration-2023-12-29.gif'
场景说明
通过streamlit run app.py运行应用时,app.py第39行的subprocess调用maps.py删除文件时触发上述错误;但直接运行python maps.py时删除操作正常,即使以管理员身份启动Streamlit也无法解决。
相关代码
app.py核心代码
import streamlit as st import base64 import os, glob import platform import subprocess import pandas as pd import datetime as dt from datetime import datetime from datetime import date class app(): def __init__(self, sys, work_dir): self.sys = sys self.work_dir = work_dir def display_gifs(self): if self.sys == "Windows": mypath = self.work_dir + "\\forecast\\fr\\" else: mypath = self.work_dir + "/forecast/fr/" os.chdir(mypath) fileslist = [] for file in glob.glob("*.gif"): print(file) fileslist.append(file) dateoffile = pd.to_datetime(fileslist[0].split("_concentration-")[1].split(".")[0],dayfirst = False) print(pd.Timestamp(date.today()) - dateoffile) if(pd.Timestamp(date.today()) - dateoffile > pd.Timedelta("1 Days")): print(pd.Timestamp(date.today()) - dateoffile) print("IN HERE") if self.sys == "Windows": subprocess.run(["python", self.work_dir + "\\DownloadCAMSforecast.py"]) subprocess.run(["python", self.work_dir + "\\maps.py"]) else: subprocess.run(["python", self.work_dir + "/DownloadCAMSforecast.py"]) subprocess.run(["python", self.work_dir + "/maps.py"]) # 读取GIF并展示的代码 file_1 = open(mypath + fileslist[0], "rb") contents = file_1.read() data_url1 = base64.b64encode(contents).decode("utf-8") file_1.close() # 省略其他文件读取和HTML展示代码... st.markdown(html_code1, unsafe_allow_html=True) st.markdown(html_code2, unsafe_allow_html=True) if __name__ == '__main__': MyApp = app(platform.system(), os.path.dirname(os.path.abspath(__file__)) ) MyApp.display_gifs()
maps.py中删除文件的代码
print('Create gif ...', flush=True, end='') if sys == "Windows": gifPath = work_dir + "\\forecast\\fr\\" else: gifPath = work_dir + "/forecast/fr/" folder = gifPath for filename in os.listdir(folder): file_path = os.path.join(folder, filename) try: if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: print('Failed to delete %s. Reason: %s' % (file_path, e))
解决思路
- 调整操作顺序:把subprocess调用
maps.py删除文件的逻辑,提前到读取GIF文件之前执行。确保删除操作发生时,当前进程没有打开这些GIF文件的句柄。 - 优化文件读取方式:将手动
open()+close()改为with语句(如with open(mypath + fileslist[0], "rb") as file_1:),确保文件句柄被可靠释放,避免隐式占用。 - 指定subprocess工作目录:调用subprocess时添加
cwd参数,指定为项目根目录,避免继承app.py的工作目录导致文件锁定问题,示例:subprocess.run(["python", self.work_dir + "\\maps.py"], cwd=self.work_dir)。 - 排查文件占用进程:用Windows工具(如Process Explorer)查看这些GIF文件被哪个进程占用,确认是否是Streamlit的主进程或子进程持有句柄,针对性释放。
- 强制延迟或重试删除:在maps.py的删除逻辑中添加重试机制,比如捕获WinError 5时等待1秒后再次尝试删除,避免短暂的文件锁定导致失败。
内容的提问来源于stack exchange,提问作者Ludogiraud
相关产品推荐
相关产品推荐

