Python通过Gmail发送邮件时DataFrame条件格式无法保留的问题求助
问题:DataFrame条件格式在Gmail邮件正文中丢失
我有一个按特定规则设置了条件格式的DataFrame,尝试通过Gmail以邮件正文(非附件)形式发送后,条件格式完全丢失了,请问问题出在哪里?
DataFrame 代码
import pandas as pd df = pd.DataFrame({'Reference': ['40%','30%'], 'colA': ['30% (20%)','25% (14%)'], 'colB': ['45% (20%)','25% (30%)'], 'colC': ['25% (30%)','35% (30%)']})
格式化DataFrame代码
def highlight(x, color1, color2): reference = x[0] ans = [None] for y in x[1:]: c = color1 if y < reference else color2 ans.append(f"background-color: {c};") return ans df = df.style.apply(highlight, color1='green', color2='red', axis=1)
邮件发送代码
from email.mime.text import MIMEText from email.mime.application import MIMEApplication from email.mime.multipart import MIMEMultipart from smtplib import SMTP import smtplib import sys recipients = ['abc@xyz.com'] emaillist = [elem.strip().split(',') for elem in recipients] msg = MIMEMultipart() msg['Subject'] = "Information" msg['From'] = 'abc@gmail.com' html = """\ <html> <head></head> <body> {0} </body> </html> """.format(df.to_html()) part1 = MIMEText(html, 'html') msg.attach(part1) server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls() server.login('abc@gmail.com', 'etehdnwyrfzgwwze') server.sendmail(msg['From'], emaillist , msg.as_string())
问题原因及解决方法
核心问题
- 字符串比较逻辑错误:直接用带格式的百分比字符串(如
'30% (20%)')和参考值(如'40%')做大小比较,是按ASCII码顺序判断的,和实际数值大小逻辑完全不符。比如'25% (30%)'字符串和'30%'的比较结果,并不是基于数值的,导致高亮规则完全失效。 - 变量覆盖问题:原代码中用
df = df.style.apply(...)覆盖了原始DataFrame,虽然不影响样式生成,但容易造成混淆,建议单独命名样式对象。
修复步骤
1. 修正数值比较逻辑
从字符串中提取括号外的百分比数值,转为浮点数后再做大小判断:
def extract_percent(s): # 提取括号前的百分比数值,去除%符号后转成浮点数 return float(s.split('(')[0].strip().replace('%', '')) def highlight(x, color1, color2): reference_val = extract_percent(x[0]) ans = [None] # Reference列不添加背景色 for y in x[1:]: y_val = extract_percent(y) c = color1 if y_val < reference_val else color2 ans.append(f"background-color: {c};") return ans # 单独存储样式对象,不覆盖原始DataFrame df_styled = df.style.apply(highlight, color1='green', color2='red', axis=1)
2. 优化邮件发送代码
- 简化收件人列表处理,添加
To邮件头使显示更规范 - 确保关闭SMTP连接,避免资源占用
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import smtplib recipients = ['abc@xyz.com'] msg = MIMEMultipart() msg['Subject'] = "Information" msg['From'] = 'abc@gmail.com' msg['To'] = ', '.join(recipients) # 添加To头 html = """\ <html> <head></head> <body> {0} </body> </html> """.format(df_styled.to_html()) part1 = MIMEText(html, 'html') msg.attach(part1) server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls() # 注意:如果开启了两步验证,需要使用Gmail应用专用密码 server.login('abc@gmail.com', 'etehdnwyrfzgwwze') server.sendmail(msg['From'], recipients, msg.as_string()) server.quit() # 关闭连接
3. 验证样式生成
可以先打印print(df_styled.to_html()),查看表格的<td>标签是否包含正确的style="background-color: green;"或red属性,确认样式生成正确后再发送邮件。
内容的提问来源于stack exchange,提问作者Prateek
相关产品推荐
相关产品推荐

