Python3.7 tkinter程序写CSV时偶发PermissionError权限错误如何解决
问题描述
我使用Python 3.7开发了一款tkinter应用,功能是从主CSV文件中提取用户预筛选的信息,生成小型报告。当前遇到的问题是:将筛选后的数据写入报告文件时偶发PermissionError,错误回溯信息如下:
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\mdiakuly\AppData\Roaming\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__ return self.func(*args) File "D:/PycharmProjects/report_extractor_hil_sil/report_extractor.py", line 286, in report_generation_prep self.report_generation(names_list, relevant_params, specific_value, extracted_file) File "D:/PycharmProjects/report_extractor_hil_sil/report_extractor.py", line 344, in report_generation processing_data(rd,column) File "D:/PycharmProjects/report_extractor_hil_sil/report_extractor.py", line 336, in processing_data writing_new_report(gathering_row) File "D:/PycharmProjects/report_extractor_hil_sil/report_extractor.py", line 299, in writing_new_report with open(extracted_file, 'a+', newline='') as write_in: PermissionError: [Errno 13] Permission denied: 'C:/Users/myusername/Desktop/reporter/Partial_report_14_10_2021T15-13-12.csv'
该错误的出现无固定规律:有时仅写入1行就触发报错,有时可完整完成全部导出无报错,还有时写入数千行后才触发报错,且写入过程中目标CSV文件始终处于未打开状态。
相关业务代码如下:
def writing_new_report(complete_row): with open(extracted_file, 'a+', newline='') as write_in: wt = csv.DictWriter(write_in, delimiter=';', fieldnames=relevant_params) if self.debug: print(complete_row) wt.writerow(complete_row) def processing_data(r_d,column='def'): for idx, row in enumerate(r_d): #looping through major csv self.progress.update() if self.debug: print(f'{idx:}',end=' / ') gathering_row = {} if column != 'def': if row[column] not in names_list: continue else: names_list.remove(row[column]) pass else: pass for param, value in zip(relevant_params,specific_value): self.progress.update() if self.debug: print(f'{row[param]:}',end=' / ') gathering_row[param] = row[param] if value == '---- All ----': pass elif value != row[param]: if self.debug: print(f'{row[param]:} - Skipped') break if param == relevant_params[len(relevant_params)-1]: if self.debug: print(f'{row[param]:} - Written') writing_new_report(gathering_row)
请问是否有人遇到过同类问题?有什么可行的修复方案?
解决方案
这个偶发权限报错是Windows系统下频繁开关同一文件的典型问题:当前逻辑是每写入一行就调用一次open打开文件再自动关闭,Windows系统的文件锁释放存在短暂延迟,杀毒软件、文件索引服务等后台进程也可能在文件关闭后短时间内持有文件锁,再次调用open就会触发权限报错。
修复方案可按优先级选择:
- 方案1:重构代码,仅打开一次文件完成所有写入(最优)
不要每行开关一次文件,在处理数据前就初始化文件对象和DictWriter,所有行写入完成后再关闭文件,从根源避免频繁开关文件的问题,同时还能提升写入效率。示例代码参考:# 在调用processing_data前先完成文件初始化 with open(extracted_file, 'w', newline='') as write_in: wt = csv.DictWriter(write_in, delimiter=';', fieldnames=relevant_params) wt.writeheader() # 如果需要写表头的话加这行 def writing_new_report(complete_row): if self.debug: print(complete_row) wt.writerow(complete_row) # 调用processing_data处理所有数据 processing_data(rd, column) - 方案2:增加写入重试机制
如果确实需要保留每次写入单独打开文件的逻辑,可以增加重试逻辑,碰到权限错误时等待短时间后重试,最多重试3-5次即可覆盖绝大多数系统锁延迟的场景。示例代码参考:import time def writing_new_report(complete_row, retry_times=3): for i in range(retry_times): try: with open(extracted_file, 'a+', newline='') as write_in: wt = csv.DictWriter(write_in, delimiter=';', fieldnames=relevant_params) if self.debug: print(complete_row) wt.writerow(complete_row) return except PermissionError: if i == retry_times -1: # 最后一次重试失败再抛出错误 raise time.sleep(0.05) # 等待50毫秒后重试 - 方案3:排除系统层面干扰(辅助)
将输出目录加入本地杀毒软件的白名单,关闭输出目录的Windows文件索引功能,减少后台进程占用文件的概率。
内容的提问来源于stack exchange,提问作者Mykola
相关产品推荐
相关产品推荐

