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

C# Process调用Python脚本二次执行时savefig报PermissionError问题

C# Process调用Python脚本重复覆盖文件时PermissionError问题

问题描述

通过C#的Process调用Python脚本时,第二次使用相同参数执行脚本会触发权限拒绝错误,该错误与savefig()覆盖已存在的.png文件有关,但直接在终端运行脚本无此问题。

错误堆栈

Traceback (most recent call last):
File (full-path)..\net6.0-windows\MakeGraph.py"
\net6.0-windows\MakeGraph.py", line 26, in savefig\r\n plt.savefig(file)
\site-packages\PIL\Image.py", line 2428, in save
\r\n fp = builtins.open(filename, "w+b")\r\nPermissionError: [Errno 13] Permission denied:

已执行的排查操作

  • 将目标文件夹改为Documents(已完成)
  • 确认路径存在(路径有效)
  • 确认目标路径指向文件(是文件)
  • 重启C#项目后可成功覆盖一次,再次执行则报错
  • 修改文件名(如"newname.png")可成功创建,但再次执行仍会报权限拒绝

相关代码片段

C# 调用代码

string fileName = csv_input.Text;
string folderName = KgBox.Text;

ProcessStartInfo PSI = new ProcessStartInfo();
PSI.FileName = @python_exe;

PSI.Arguments = string.Format("{0} {1} {2}", sript_py, fileName, folderName);
PSI.UseShellExecute = false;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.CreateNoWindow = true;
try
{
    using (Process? p = Process.Start(PSI))
    {
        p.WaitForExit();
        status_from_script += p.StandardOutput.ReadToEnd();
        status_from_script += p.StandardError.ReadToEnd();
        ErrorBox.Text += status_from_script;
    }
}

Python 脚本核心代码

def savefig(dataframe, title):
plt.plot(dataframe)
plt.xlabel("data point")
plt.ylabel("Acceleration (m/s^2)")
plt.title(title)
y = [1,-30,-60,-90,-120, -150, -180, -210, -240, -270, -300, -330]
plt.yticks(y)
file = save_path + "\\\\"+ csv_folder + ".png"
print(file)
plt.savefig(file)
plt.close()
print("DONE")

解决方案

问题根源是文件被未完全释放的进程或资源占用,以下是针对性解决步骤:

1. 彻底释放Python侧的matplotlib资源

仅调用plt.close()可能无法完全释放图形资源,需改为:

def savefig(dataframe, title):
    # ... 原有绘图代码 ...
    file = save_path + "\\\\"+ csv_folder + ".png"
    print(file)
    # 使用文件句柄模式保存,确保显式关闭
    with open(file, 'wb') as f:
        plt.savefig(f)
    plt.close('all')  # 关闭所有matplotlib图形实例
    print("DONE")

plt.close('all')会清理所有关联的图形对象,避免隐式占用文件句柄。

2. 确保C#侧进程资源完全释放

虽然using块会自动释放进程,但可显式调用Close()和Dispose()确保资源回收:

using (Process? p = Process.Start(PSI))
{
    p.WaitForExit();
    // 先读取输出,再清理进程
    string output = p.StandardOutput.ReadToEnd();
    string error = p.StandardError.ReadToEnd();
    status_from_script += output + error;
    ErrorBox.Text += status_from_script;
    // 显式释放进程资源
    p.Close();
    p.Dispose();
}

同时检查C#项目中是否有其他组件(如图片预览控件)正在占用生成的.png文件,需先解除该引用。

3. 添加文件写入重试机制

针对临时占用的情况,在Python脚本中添加重试逻辑:

import time

def savefig(dataframe, title):
    # ... 原有绘图代码 ...
    file = save_path + "\\\\"+ csv_folder + ".png"
    print(file)
    max_retries = 3
    retry_delay = 1  # 等待1秒后重试
    success = False
    for attempt in range(max_retries):
        try:
            with open(file, 'wb') as f:
                plt.savefig(f)
            success = True
            break
        except PermissionError:
            if attempt < max_retries - 1:
                time.sleep(retry_delay)
            else:
                raise
    if success:
        plt.close('all')
        print("DONE")

内容的提问来源于stack exchange,提问作者Kenneth Køpke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:20:30