如何在Python中结合列表与字典实现MySQL8收件人对应产品告警邮件功能?
解决思路与优化方案
首先,咱们先梳理下你当前代码的核心问题:
- 你把所有收件人的产品都放到了同一个全局
products列表里,导致后续遍历收件人时,每个收件人都会拿到所有产品,而不是只匹配自己厂商ID的产品 - 用列表存储收件人和产品信息,缺乏明确的键值关联,后续匹配和取值都很麻烦
- SQL执行时的参数传递有问题:
( recipient[0] )不是合法的元组,单个参数的元组需要写成(recipient[0],),否则会触发参数错误 - 邮件内容生成时,你错误地用
recipient(收件人信息)去填充availability_list,而不是对应的产品列表
针对你的需求,用字典来组织数据会更清晰,因为字典可以通过键值对直接关联收件人和其对应的产品,避免后续匹配的麻烦。下面是优化后的完整实现思路:
1. 重构数据结构:用字典存储收件人及关联产品
我们可以把每个收件人封装成一个字典,包含其基本信息,同时新增一个products键来存储该收件人对应的告警产品,这样后续发送邮件时直接取这个值即可。
2. 优化数据库操作:用with语句自动管理连接/游标
with语句会自动帮你关闭游标和连接,避免手动关闭时可能出现的遗漏或错误。
3. 完整优化代码示例
import mysql.connector from tabulate import tabulate def fetch_recipients_with_products(conn): recipients = [] # 获取所有收件人,并初始化每个收件人的产品列表 with conn.cursor(buffered=True) as curb: curb.execute(""" SELECT MANUFACTURER_ID, EMAIL, NAME FROM manufacturers_alerts_recipients """) for row in curb.fetchall(): recipient_dict = { "manufacturer_id": row[0], "email": row[1], "name": row[2], "products": [] # 用于存储当前收件人的告警产品 } recipients.append(recipient_dict) # 为每个收件人查询对应的产品,并关联到自身的products字段 for recipient in recipients: with conn.cursor(buffered=True) as curb: # 注意参数元组的逗号:(recipient["manufacturer_id"],) curb.execute(""" SELECT TITLE, ARTICLE_ID, NAME, AVAILABILITY FROM merchants_product_catalog WHERE manufacturer_id = %s """, (recipient["manufacturer_id"],)) for product_row in curb.fetchall(): # 将产品信息转为字典(可选,也可以用列表,但字典可读性更强) product_dict = { "title": product_row[0], "article_id": product_row[1], "name": product_row[2], "availability": product_row[3] } recipient["products"].append(product_dict) return recipients def send_alert_emails(recipients): for recipient in recipients: if not recipient["products"]: print(f"跳过收件人 {recipient['name']}:无对应告警产品") continue # 生成邮件内容:用当前收件人的products列表 # 如果需要保持列表格式,也可以直接用product_row的列表形式 product_list = [[p["title"], p["article_id"], p["name"], p["availability"]] for p in recipient["products"]] body_txt = tabulate(product_list, headers=['PRODUCT', 'SKU', 'POS', 'AVAILABILITY']) print(f"准备发送邮件到 {recipient['email']}") print("邮件内容:") print(body_txt) print("---") # 这里替换成实际的邮件发送代码 # sendmail(recipient['email'], subject, body_txt) if __name__ == "__main__": # 初始化数据库连接 try: conn = mysql.connector.connect( host="your_host", user="your_user", password="your_password", database="your_db" ) recipients_with_products = fetch_recipients_with_products(conn) send_alert_emails(recipients_with_products) except mysql.connector.Error as error: print(f"数据库连接/查询错误:{error}") finally: if conn.is_connected(): conn.close()
关键优化点说明
- 数据关联更清晰:每个收件人的产品直接存在自身的
products字段中,无需后续再通过厂商ID匹配,避免了全局列表的混乱 - 参数传递正确:修复了SQL参数的元组格式问题,避免执行报错
- 可读性更强:用字典存储收件人和产品,字段名明确,后续维护更方便
- 资源自动管理:
with语句自动关闭游标,避免资源泄漏 - 空值处理:如果某个收件人没有对应产品,会跳过发送,避免发送空邮件
内容的提问来源于stack exchange,提问作者merlin
相关产品推荐
相关产品推荐

