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
相关产品推荐
相关产品推荐

