Windows下os.path错误修复及Python带附件邮件发送OSError排查
1. 修复Windows机器上的os.path错误的常见方案
在Windows上处理路径时,很容易因为分隔符、格式问题踩坑,这里给你几个实用的解决思路:
- 用原生工具拼接路径:别手动写反斜杠或者正斜杠,直接用
os.path.join()或者Python3.4+的pathlib.Path来拼接路径,它们会自动适配Windows的路径规则,比如os.path.join("C:", "Users", "n123456", "Desktop")或者Path("C:/Users") / "n123456" / "Desktop"。 - 验证路径有效性:在操作文件前,先用
os.path.exists(your_path)或者Path(your_path).exists()检查路径是否真的存在,避免无效路径导致的错误。 - 注意权限问题:如果访问系统目录或者受保护的文件夹,确保你的Python程序有足够的权限,必要时右键以管理员身份运行脚本。
- 正确处理字符串里的反斜杠:Windows路径用反斜杠
\,但在Python字符串里它是转义字符,所以要么用原始字符串r"C:\Users\...",要么把反斜杠写成\\,比如"C:\\Users\\..."。 - 避开特殊字符:如果路径里有空格或者特殊符号,尽量用原始字符串包裹,或者用
pathlib来处理,它会自动处理这些情况。
2. 修复带附件发送邮件的Python函数错误
咱们先看你遇到的核心问题:报错里的路径带着单引号'C:\\Users\\...',这明显不是一个合法的文件路径——问题出在你处理*FILETOSEND元组的方式上。
错误根源分析
当你用*FILETOSEND作为函数参数时,它会把传入的多个参数打包成一个元组。比如你传入单个文件路径,得到的元组是('C:\\Users\\...',),你把这个元组转成字符串后变成了"('C:\\Users\\...',)",再切片取[1:-2]就得到了带单引号的路径,系统自然找不到这个文件。另外,你调用函数时写的sendEmail(..., *FILETOSEND)也有问题:*会把字符串拆成单个字符,导致元组里全是单个字符,这完全不对。
修正后的完整代码
我给你调整了函数,解决了这些问题,还优化了文件处理的安全性:
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import os # 用来处理文件名 def sendEmail(TO, FROM, SUBJECT, BODY, *FILETOSEND): """Function to send email with optional attachments""" # 创建邮件容器 msg = MIMEMultipart("alternative") msg["Subject"] = SUBJECT msg["From"] = FROM msg["To"] = TO # 处理附件(支持多个附件) if FILETOSEND: for file_path in FILETOSEND: # 先检查文件是否存在,提前拦截错误 if not os.path.exists(file_path): print(f"警告:文件 {file_path} 不存在,跳过该附件") continue # 使用with语句自动关闭文件,避免资源泄漏 with open(file_path, 'r', encoding='utf-8') as fp: attachment = MIMEText(fp.read()) # 获取文件名,避免把完整路径作为附件名展示 filename = os.path.basename(file_path) attachment.add_header( "Content-Disposition", "attachment", filename=filename ) msg.attach(attachment) # 添加邮件正文 part1 = MIMEText(BODY, "plain") msg.attach(part1) # 发送邮件,用with语句自动关闭SMTP连接 try: with smtplib.SMTP("smtpservername") as s: # 如果你的SMTP服务器需要登录,取消下面两行注释并填入密码 # s.login(FROM, "你的邮箱密码") s.sendmail(FROM, TO, msg.as_string()) print("邮件发送成功") except Exception as e: print(f"邮件发送失败:{str(e)}") # 正确的调用方式 fileToSend = r"C:\Users\n123456\Desktop\DomainFolder\D1\NEWDATASET.txt" # 注意:这里不要加*,直接传入文件路径即可;如果要传多个附件,用逗号分隔 sendEmail(TO, FROM, SUBJECT, BODY, fileToSend) # 多附件示例:sendEmail(TO, FROM, SUBJECT, BODY, fileToSend, another_file_path)
关键修复点说明
- 直接遍历元组:不再把元组转成字符串切片,而是直接遍历
FILETOSEND里的每个文件路径,支持同时传入多个附件。 - 文件存在性检查:提前判断文件是否存在,避免触发文件未找到错误,还能给出明确提示。
- 用with语句管理文件:自动关闭文件,比手动调用
fp.close()更安全,不会因为代码异常导致文件句柄泄漏。 - 正确设置附件文件名:用
os.path.basename()提取文件名,收件人看到的会是NEWDATASET.txt而不是完整路径。 - 修正函数调用:去掉调用时的
*,直接传入文件路径,避免字符串被拆分成单个字符。
额外建议
如果要发送非文本类型的附件(比如图片、压缩包),可以改用MIMEBase来处理,示例代码如下:
from email.mime.base import MIMEBase from email import encoders # 在处理附件的循环里替换成这段代码 with open(file_path, 'rb') as fp: attachment = MIMEBase('application', 'octet-stream') attachment.set_payload(fp.read()) encoders.encode_base64(attachment) filename = os.path.basename(file_path) attachment.add_header( "Content-Disposition", "attachment", filename=filename ) msg.attach(attachment)
内容的提问来源于stack exchange,提问作者Chinmay Nayak
相关产品推荐
相关产品推荐

