Unix环境下使用Python发送多附件邮件时出现IOError报错原因排查
附件发送报错IOError的排查思路与修正方案
核心定位
你遇到的报错IOError: [Errno 2] No such file or directory: /,本质是代码执行到with open(path, 'rb')时,传入open的路径值就是单字符的根目录/,根本没有遍历到你在主函数里写的两个/home/test/开头的附件路径。结合你的代码结构,常见触发原因如下:
- 可变默认参数的Python通用陷阱:函数定义时使用
files=[]作为默认参数,这类可变对象只会在函数定义阶段初始化一次,后续所有调用如果没显式传入files列表,都会复用同一个全局列表对象。如果之前调试运行时,曾经往这个默认列表里追加过空字符串、根路径/这类异常值,这些残留值会在后续运行中被遍历到,触发open报错。 - 附件列表存在冗余异常元素:检查你之前注释掉的命令行参数读取逻辑,是否存在残留的拼接代码,把命令行传入的空参数、错误根路径拼接到files列表中。哪怕主函数里显式传了正确路径,如果列表拼接逻辑出错,依然会混入值为
/的无效元素。 - 动态读取路径时出现截断:如果后续把附件路径改成从配置文件、命令行动态读取,可能因为换行、shell转义字符导致长路径被截断成单字符的
/,也会触发同类报错。你目前主函数写死路径的场景下出现这个问题,基本可以排除该原因。
可直接落地的排查步骤
- 把循环第一行的打印语句从
print(path)改成print(repr(path)),直接输出当前遍历路径的原始字符串值,精确定位哪个迭代步骤拿到的path是/ - 增加前置路径校验,不要等open抛出模糊的IOError:
for path in files: print(f"正在处理附件: {repr(path)}") if not op.exists(path): raise IOError(f"附件路径不存在,请检查: {path}") part = MIMEBase('application', "octet-stream") with open(path, 'rb') as file: part.set_payload(file.read()) - 修正可变默认参数的写法,从根源避免列表残留问题:
把函数定义里的默认参数files=[]改成files=None,函数内部做空值初始化:def send_mail(send_from, send_to, send_cc, subject, message, files=None, server="serveripaddress"): if files is None: files = []
补充易忽略的校验点
- 确认运行脚本的Unix用户对两个附件文件有可读权限,权限不足也会触发IOError,只是报错提示会明确标识权限问题,和当前路径不存在的报错有明确区别
- 确认附件路径对应的目录没有出现自动挂载失效、软链接指向空路径的问题,避免出现路径看起来存在,但实际无法访问的情况
内容的提问来源于stack exchange,提问作者Rahul Wagh
相关产品推荐
相关产品推荐

