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

Python发送邮件报错TypeError: 'NoneType'不可迭代的排查与修复

TypeError: 'NoneType' object is not iterable when fetching email from database in Python email-sending code

我正在用Python发送邮件,但运行代码时碰到了这个错误:

TypeError: 'NoneType' object is not iterable

错误出现在这一行:email = list(cursor.fetchone())

我的代码如下:

@app.route('/send_mail', methods = ['POST'])
def send_mail():
    test_append = str(request.form['folder_name'])
    teacher_name = str(session.get('user'))
    excel_dir = APP_ROOT + "/excel/" + test_append + "/" + teacher_name + "/"
    excel_date = request.form['fname']
    time = request.form['ftime']
    time = time[: 2]
    final_send = glob(excel_dir + "/" + excel_date + "@" + time + "*.xlsx")[0]
    print(final_send)
    df = pd.read_excel(final_send)
    roll_id = list(df['Roll Id'])
    print(type(roll_id))
    print(roll_id)
    cursor = conn.cursor()
    for i in range(len(roll_id)):
        cursor.execute("SELECT student_email,parent_email from student_login where binary roll_id=%s", [roll_id[i]])
        email = list(cursor.fetchone())
        print(type(email[1]))
        print(email[0])
        print(email[1])
        msg = Message('Auto Generated', recipients = [email[0], email[1]])
        msg.body = "Hi.. " + roll_id[i] + " is present for the lecture of " + "Prof. " + str(teacher_name.split('.', 1)[0]) + ", which is held on " + excel_date + "@" + time + "hrs"
        msg.html = "Hi.. " + roll_id[i] + " is present for the lecture of " + "Prof. " + str(teacher_name.split('.', 1)[0]) + ", which is held on " + excel_date + "@" + time + "hrs"
        mail.send(msg)
    return "<h1>mail sent<h1>"

请问问题根源是什么,该如何修复?


问题根源

这个错误的核心原因很直接:当你执行cursor.fetchone()时,它返回了None——这意味着你的数据库里没有找到对应roll_id[i]的记录。而你直接把None传给list()函数,自然会抛出'NoneType' object is not iterable的错误,因为None不是可迭代对象,没法转成列表。

为什么会找不到记录?常见场景有这几种:

  • Excel里的Roll Id值和数据库student_login表中的roll_id不匹配(比如大小写、空格、特殊字符差异,你用了binary关键字,会严格区分大小写和字节)
  • 某些Roll Id在数据库里确实不存在
  • 少数情况是SQL参数绑定出错,但看你的写法[roll_id[i]]是正确的,这个可能性很低

修复方案

你需要在代码里先判断fetchone()的结果是否为None,再进行后续处理,避免直接操作空值。这里提供两种实用的处理方式:

方式1:跳过不存在的记录(并打印日志)

这种方式适合允许部分ID不存在的场景,直接跳过异常记录继续发送其他邮件:

for i in range(len(roll_id)):
    current_roll = roll_id[i]
    cursor.execute("SELECT student_email,parent_email from student_login where binary roll_id=%s", [current_roll])
    result = cursor.fetchone()
    # 先检查结果是否存在
    if result is None:
        print(f"警告:Roll ID {current_roll} 在数据库中找不到对应的记录,跳过发送邮件")
        continue
    # 存在的话再转成列表
    email = list(result)
    print(type(email[1]))
    print(email[0])
    print(email[1])
    # 后续邮件发送代码,这里可以复用body内容减少冗余
    msg = Message('Auto Generated', recipients = [email[0], email[1]])
    msg.body = f"Hi.. {current_roll} is present for the lecture of Prof. {teacher_name.split('.', 1)[0]}, which is held on {excel_date}@{time}hrs"
    msg.html = msg.body
    mail.send(msg)

方式2:提前批量校验数据(从根源避免问题)

如果Excel里的Roll Id应该全部存在于数据库中,那可以先批量校验哪些ID不存在,统一提示或处理:

# 先获取数据库中所有有效的roll_id
cursor.execute("SELECT roll_id FROM student_login")
existing_rolls = {row[0] for row in cursor.fetchall()}

# 筛选出Excel中存在但数据库中不存在的ID
missing_rolls = [rid for rid in roll_id if rid not in existing_rolls]
if missing_rolls:
    print(f"以下Roll ID在数据库中不存在:{missing_rolls}")
    # 这里可以选择返回错误提示给前端,或者继续发送其他邮件
    # return f"<h1>警告:存在无效Roll ID {missing_rolls}</h1>"

# 只处理数据库中存在的ID
for current_roll in roll_id:
    if current_roll not in existing_rolls:
        continue
    cursor.execute("SELECT student_email,parent_email from student_login where binary roll_id=%s", [current_roll])
    email = list(cursor.fetchone())
    # 后续邮件发送代码不变
    ...

另外提个小优化:你的邮件body和html内容完全一样,可以直接用msg.html = msg.body来减少代码冗余,看起来更整洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:07:33