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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:35:54