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

将BigQuery循环查询结果嵌入Python smtplib邮件正文报错求助

解决方法:让函数返回邮件正文内容,而非仅打印

这个错误的根源很明确:你的query_named_params函数没有返回任何值(默认返回None),但smtplib.SMTP.sendmail()的第三个参数需要是一个字符串格式的邮件内容,它尝试计算None的长度时就触发了TypeError。

我们需要调整两个核心部分:

1. 修改查询函数,让它返回格式化后的结果字符串

把原来直接print的逻辑改成收集结果到一个字符串里,最后返回这个字符串:

def query_named_params(corpus, min_word_count):
    client = bigquery.Client()
    query = """
        SELECT word, word_count
        FROM `bigquery-public-data.samples.shakespeare`
        WHERE corpus = @corpus
        AND word_count >= @min_word_count
        ORDER BY word_count DESC;
    """
    query_params = [
        bigquery.ScalarQueryParameter('corpus', 'STRING', 'sonnets'),
        bigquery.ScalarQueryParameter('min_word_count', 'INT64', 10)
    ]
    job_config = bigquery.QueryJobConfig()
    job_config.query_parameters = query_params
    query_job = client.query(query, job_config=job_config)
    
    # 收集结果到字符串,而不是直接打印
    result_text = "莎士比亚十四行诗中出现次数≥10的单词:\n\n"
    for row in query_job.result():  # 直接用query_job.result()更简洁,不用再获取表
        result_text += "{} : {} 次\n".format(row.word, row.word_count)
    
    return result_text  # 返回结果字符串

这里我还简化了获取结果的逻辑,直接用query_job.result()遍历行,比先获取目标表再list_rows更高效。

2. 构建完整的邮件内容(包含主题头)

纯文本邮件需要加上Subject头,不然收件方看到的邮件会没有主题。我们先获取查询结果,再拼接成完整的邮件内容:

# --------------------EMAIL PORTION -------------#
print('Starting email send...')
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(login_email, login_pwd)

# 获取查询结果文本
query_result = query_named_params('corpus', 'min_word_count')
# 构建完整邮件内容,添加主题
msg = """Subject: BigQuery 莎士比亚数据查询结果

{}
""".format(query_result)

# 发送邮件,传入正确的邮件内容字符串
server.sendmail(login_email, recipients, msg)
server.quit()

完整修改后的代码

from google.cloud import bigquery
import smtplib

# Variables
login_email = 'MYEMAIL'
login_pwd = 'MYPASSWORD'
recipients = 'EMAILSENDINGTO'

# Create a function
def query_named_params(corpus, min_word_count):
    client = bigquery.Client()
    query = """
        SELECT word, word_count
        FROM `bigquery-public-data.samples.shakespeare`
        WHERE corpus = @corpus
        AND word_count >= @min_word_count
        ORDER BY word_count DESC;
    """
    query_params = [
        bigquery.ScalarQueryParameter('corpus', 'STRING', 'sonnets'),
        bigquery.ScalarQueryParameter('min_word_count', 'INT64', 10)
    ]
    job_config = bigquery.QueryJobConfig()
    job_config.query_parameters = query_params
    query_job = client.query(query, job_config=job_config)
    
    # 收集结果为字符串
    result_text = "莎士比亚十四行诗中出现次数≥10的单词:\n\n"
    for row in query_job.result():
        result_text += "{} : {} 次\n".format(row.word, row.word_count)
    
    return result_text

# --------------------EMAIL PORTION -------------#
print('Starting email send...')
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(login_email, login_pwd)

# 获取查询结果并构建邮件
query_result = query_named_params('corpus', 'min_word_count')
msg = """Subject: BigQuery 莎士比亚数据查询结果

{}
""".format(query_result)

server.sendmail(login_email, recipients, msg)
server.quit()

if __name__ == '__main__':
    # 测试查询函数(可选)
    print(query_named_params('corpus','min_word_count'))

额外注意事项

  • 如果你的Gmail账号开启了两步验证,需要用应用专用密码代替原密码登录,不然会触发登录失败。
  • 确保你的Python环境已经正确安装google-cloud-bigquery库,并且配置了BigQuery的认证凭据(比如环境变量或密钥文件)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:45:57