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

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)

关键修复点说明

  1. 直接遍历元组:不再把元组转成字符串切片,而是直接遍历FILETOSEND里的每个文件路径,支持同时传入多个附件。
  2. 文件存在性检查:提前判断文件是否存在,避免触发文件未找到错误,还能给出明确提示。
  3. 用with语句管理文件:自动关闭文件,比手动调用fp.close()更安全,不会因为代码异常导致文件句柄泄漏。
  4. 正确设置附件文件名:用os.path.basename()提取文件名,收件人看到的会是NEWDATASET.txt而不是完整路径。
  5. 修正函数调用:去掉调用时的*,直接传入文件路径,避免字符串被拆分成单个字符。

额外建议

如果要发送非文本类型的附件(比如图片、压缩包),可以改用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:48:15