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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 20:07:28