You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Openpyxl保存文件无报错但Shell重启,生成0字节损坏文件

Troubleshooting Openpyxl Save Causing Python Shell Crash & 0-Byte Excel File

我之前也碰到过类似的openpyxl保存时崩溃的问题,结合你的代码和场景,给你几个排查方向和修复建议:


1. Write-Only模式的误用是核心问题

你先通过write_only=True加载复制后的文件,修改标题后保存,接着又用常规模式重新加载修改数据——这种混合使用读写模式的操作很容易破坏Excel文件结构,甚至触发Python解释器崩溃。Write-only模式是为批量写入大量数据设计的,它不支持后续的读取/修改操作。

修复代码示例

# 直接用默认读写模式加载复制后的文件,无需分两次操作
faylneym = f"DC{kw_num}.xlsx"
paf = os.path.join(values['Browse0'], faylneym)
shutil.copy2(values['Browse1'], paf)

# 去掉write_only=True,用默认模式加载
dcwb = load_workbook(paf)
dcws = dcwb['KW_XX']
dcws.title = str(kw)

# 直接在这里填充所有数据
for x,y in enumerate(strdate, start=2):
    dcws[f'A{x}'].value = y
for x,y in enumerate(strdate, start=12):
    dcws[f'A{x}'].value = y
for x,y in enumerate(hours_from_eos2, start=2):
    dcws[f'E{x}'].value = y
for x,y in enumerate(full_endlist_data.values(), start=2):
    dcws[f'D{x}'].value = y

# 所有数据填充完成后,只调用一次保存
dcwb.save(paf)
dcwb.close()

2. with语句管理工作簿,避免文件句柄泄漏

手动调用close()有时候会因为异常导致未执行,残留的文件句柄会和后续保存操作冲突,引发崩溃。用with语句可以自动管理工作簿的打开和关闭:

优化endlist处理代码

with load_workbook(f"Endlist_{monat1}_2019.xlsx", data_only=True) as endlist:
    endlistws = endlist.active
    endlist_hrs = {}
    # 一次遍历完成数据收集,减少重复循环
    for cell in endlistws['A']:
        if cell.value is None:
            continue
        cell_date = dateConverter(cell.value)
        if weeknum(cell_date) != kw_num:
            continue
        # 初始化字典键(不存在则创建)
        if cell_date not in endlist_hrs:
            endlist_hrs[cell_date] = []
        # 直接添加J列的时间值
        endlist_hrs[cell_date].append(czasownik(endlistws[f'J{cell.row}'].value))

# 退出with块后自动关闭工作簿,无需手动close()
full_endlist_data = {k:sum(v) for (k,v) in endlist_hrs.items()}

3. 版本兼容性排查

你使用的Python 3.6.7 + openpyxl 3.0.2组合存在一些已知的兼容性bug,尤其是在处理复杂Excel模板时。建议:

  • 升级openpyxl到3.1.x版本(该版本仍支持Python 3.6)
  • 检查你的模板文件是否包含复杂元素(合并单元格、宏、特殊条件格式),尝试用简化版模板测试,排除格式导致的崩溃

4. 减少内存占用,避免解释器崩溃

你的原代码中两次遍历A列构建endlist_hrs,会额外消耗内存和CPU资源。上面的优化代码已经改成一次遍历完成,能有效降低内存负载,减少因内存耗尽导致的Shell重启。


内容的提问来源于stack exchange,提问作者Michał Lewandowski

火山引擎 最新活动