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
相关产品推荐
相关产品推荐

