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

Windows下用ReportLab保存PDF遇PermissionError[Errno13]权限拒绝求助

解决ReportLab在Windows下保存PDF时的PermissionError问题

看起来你遇到的核心问题是默认保存路径没有写入权限——虽然你能成功把CSV存到D:/Course/roi report auto/,但生成PDF时用的是相对路径testing.pdf,它会被存在Spyder的当前工作目录里(这个目录可能是系统受限的路径,比如C:\Users\XXX\Documents或者Spyder安装目录),哪怕用管理员运行,当前工作目录的权限限制依然存在。

下面是具体的解决步骤和代码修改建议:

1. 给PDF指定有写入权限的完整路径

既然你已经确认D:/Course/roi report auto/目录可以正常写入CSV,直接把PDF也保存在同一个目录里就好。修改pdf_file_name为带完整路径的文件名,还可以加上时间戳避免文件覆盖:

# 把这行修改为带完整路径的命名
pdf_file_name = f'D:/Course/roi report auto/testing_{timestr}.pdf'

2. 修复import_data函数里的循环问题

你的import_data函数里有个小bug:for row in final_dataset:遍历的是DataFrame的列名,这会导致generate_pdf被调用多次(次数等于列数),不仅冗余还可能导致文件被占用。如果你的DataFrame是单条汇总数据,直接去掉循环即可:

def import_data(final_dataset):
    # 去掉多余的for循环,直接读取数据
    Start_date = final_dataset.iloc[1,1] # 开始日期
    End_date = final_dataset.iloc[6,1] # 结束日期
    Total_cost = final_dataset.iloc[0,7]# 总费用
    Total_impressions = final_dataset.iloc[0,5]# 总曝光量
    Total_clicks = final_dataset.iloc[0,6]# 总点击量
    Effective_CPM = final_dataset.iloc[0,8]# 有效CPM
    Title = final_dataset.iloc[0,0]
    # 用带完整路径的文件名
    pdf_file_name = f'D:/Course/roi report auto/testing_{timestr}.pdf'
    generate_pdf(Start_date, End_date, Total_cost, Total_impressions, Total_clicks, Effective_CPM, pdf_file_name)

3. 额外的权限排查点

如果修改路径后还是报错,可以检查这几点:

  • 确认D:/Course/roi report auto/目录的权限:右键目录→属性→安全,确保你的用户账号(或管理员组)拥有写入权限。
  • 关闭可能正在打开目标PDF的程序:如果PDF已经被阅读器打开,系统会锁定文件导致无法写入。
  • 避免保存到系统保护目录:比如C:\Program Files、C:\Windows这类目录,哪怕管理员也需要额外权限,尽量用自定义的用户目录。

修改后的完整代码片段(关键部分)

timestr = pd.Timestamp.now().strftime('%Y%m%d_%H%M%S') # 假设你定义了timestr
# 将数据框保存为CSV
df.to_csv(f'D:/Course/roi report auto/sidebanner_datasheet_{timestr}.csv', index=False)
# ReportLab相关代码
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, portrait

final_dataset = pd.read_csv(f'D:/Course/roi report auto/sidebanner_datasheet_{timestr}.csv')

def import_data(final_dataset):
    Start_date = final_dataset.iloc[1,1]
    End_date = final_dataset.iloc[6,1]
    Total_cost = final_dataset.iloc[0,7]
    Total_impressions = final_dataset.iloc[0,5]
    Total_clicks = final_dataset.iloc[0,6]
    Effective_CPM = final_dataset.iloc[0,8]
    Title = final_dataset.iloc[0,0]
    # 指定完整保存路径
    pdf_file_name = f'D:/Course/roi report auto/testing_{timestr}.pdf'
    generate_pdf(Start_date, End_date, Total_cost, Total_impressions, Total_clicks, Effective_CPM, pdf_file_name)

def generate_pdf(Start_date, End_date, Total_cost, Total_impressions, Total_clicks, Effective_CPM, pdf_file_name):
    # 用指定的完整路径创建Canvas
    r = canvas.Canvas(pdf_file_name, pagesize=portrait(A4))
    # 页眉文本(调整了y坐标,让内容显示在页面上方)
    r.setFont('Helvetica', 22)
    r.drawCentredString(207, 750, "The Hello World")
    r.setFont('Helvetica', 12)
    r.drawCentredString(207, 730, "Hello World")
    r.showPage()
    r.save()

# 调用函数生成PDF
import_data(final_dataset)

(注:调整了drawCentredString的y坐标,因为A4 portrait页面的高度是841点,原来的200会在页面底部几乎看不见,改成750更符合页眉的显示位置)

内容的提问来源于stack exchange,提问作者Gaël Latouche

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:06:09