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

Linux挂载NAS时Python openpyxl读存在的xlsx报文件不存在

openpyxl读取xlsx文件抛出no such file or directory错误

异常表现

  • 所有相关文件(.py脚本、.xlsx数据文件)均存储在NAS设备上,脚本逻辑为读取多个不同目录下的.xlsx文件
  • 在macOS系统下通过SMB协议访问NAS运行脚本时,所有流程运行正常,文件均可正常读取
  • 在服务器部署的Linux虚拟机中,通过mount挂载方式访问NAS运行脚本时,前2个.xlsx文件可正常读取,读取第3个文件时触发报错。该异常文件是从Gmail邮件中下载保存的,手动可正常打开无损坏,经核对文件名100%匹配,Python运行的工作目录配置正确。

相关代码

Gmail邮箱下载保存附件实现

mail = imaplib.IMAP4_SSL("imap.gmail.com" )
mail.login("mail@gmail.com","password")
mail.select('INBOX')
data = mail.search(None, 'ALL')
mail_ids = data[1]
id_list = mail_ids[0].split()
if len(id_list)>=1:
    first_email_id = int(id_list[0])
    latest_email_id = int(id_list[-1])

    for i in range(latest_email_id,first_email_id-1, -1):
        data = mail.fetch(str(i), '(RFC822)' )
        for response_part in data:
            arr = response_part[0]
            if isinstance(arr, tuple):
                msg = email.message_from_string(str(arr[1],'utf-8'))
                email_subject = msg['subject']
                email_to = msg['to']

                counter = 1
                for part in msg.walk():
                    # multipart/* are just containers
                    if part.get_content_maintype() == 'multipart':
                        continue
                    filename = part.get_filename()
                    if not filename:
                        ext = mimetypes.guess_extension(part.get_content_type())
                        if not ext:
                            # Use a generic bag-of-bits extension
                            ext = '.bin'
                        filename = f'part-{counter:03d}{ext}'
                    counter += 1
                    if ".xls" in filename:
                        with open(os.path.join(".", filename), 'wb') as fp:
                            fp.write(part.get_payload(decode=True))

报错触发位置代码

if xyz == 1:
    Excel = "Gleichmäßigkeit_A+R.xlsx"
...
os.chdir("Klassen")
TKlasse1 = lw(Excel) # this file cant be opened, "lw" for openpyxl.load_workbook
TKlasse1 = TKlasse1["WL1"]

完整报错输出

paul@elementary:/mnt/paul/server/dhm$ python3 DHM.py
Traceback (most recent call last):
  File "DHM.py", line 347, in <module>
    TKlasse1 = lw(Excel)
  File "/usr/local/lib/python3.8/dist-packages/openpyxl/reader/excel.py", line 315, in load_workbook
    reader = ExcelReader(filename, read_only, keep_vba,
  File "/usr/local/lib/python3.8/dist-packages/openpyxl/reader/excel.py", line 124, in __init__
    self.archive = _validate_archive(fn)
  File "/usr/local/lib/python3.8/dist-packages/openpyxl/reader/excel.py", line 96, in _validate_archive
    archive = ZipFile(filename, 'r')
  File "/usr/lib/python3.8/zipfile.py", line 1251, in __init__
    self.fp = io.open(file, filemode)
FileNotFoundError: [Errno 2] No such file or directory: 'Gleichmäßigkeit_A+R.xlsx'

问题根因

  1. 附件文件名未做规范解码:直接调用part.get_filename()获取带变音符号(比如ä)的文件名时,没有处理邮件头的编码格式,保存到NAS上的文件名和代码中硬写的文件名字节序列不一致。肉眼看两个文件名完全相同,但其中的特殊字符一个是Unicode预组合形式、一个是基础字符+变音标记的组合形式,属于典型的Unicode同形异码问题。
  2. 系统/协议的文件名兼容逻辑差异:macOS的SMB客户端默认会自动做文件名Unicode标准化(NFC/NFD自动转换),哪怕文件名字节序列有差异也能匹配到文件;Linux下mount挂载NAS时默认不会做这类自动转换,前两个文件名不含特殊字符所以读取正常,第三个带变音符号的文件无法匹配,最终抛出文件不存在的错误。

修复方案

  • 修正附件下载逻辑:不要直接使用part.get_filename()的返回值,引入邮件头解码逻辑,保证保存到磁盘的文件名是标准UTF-8编码字符串,替换文件名获取部分的代码如下:
from email.header import decode_header
from email.utils import unquote

raw_filename = part.get_filename()
filename = ""
if raw_filename:
    decoded_parts = decode_header(unquote(raw_filename))
    for content, encoding in decoded_parts:
        if isinstance(content, bytes):
            filename += content.decode(encoding or "utf-8")
        else:
            filename += content
else:
    ext = mimetypes.guess_extension(part.get_content_type())
    if not ext:
        ext = '.bin'
    filename = f'part-{counter:03d}{ext}'
  • 存量文件处理:如果已经把文件保存到NAS上,进入Linux虚拟机的Klassen目录,执行ls | od -c查看目标文件的实际文件名字节,要么把代码里的文件名替换为和实际存储完全一致的字符串,要么直接重命名文件,尽量使用纯ASCII字符命名,规避特殊字符的编码兼容问题。
  • 编码习惯优化:尽量避免使用os.chdir()切换工作目录,改用os.path.join()拼接文件的绝对路径传入load_workbook,减少工作目录意外变动导致的路径错误。

内容的提问来源于stack exchange,提问作者user18977494

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:36:36