Python烧瓶多进程:无法“呈现”用于发送网格电子邮件正文的html页面
Posted
技术标签:
【中文标题】Python烧瓶多进程:无法“呈现”用于发送网格电子邮件正文的html页面【英文标题】:Python flask multiprocess: cannot "render" a html page for the send grid email body 【发布时间】:2022-01-13 17:09:35 【问题描述】:为了带来一些背景,我有一个很大的特定功能,它作为一个多进程在后台运行。也就是第二个过程(以后可能会更多)。
这样做的原因是它会重定向到一个表明请求成功的 html 页面。 毕竟,在他的数据请求通过并转换数据之前,客户不会在加载页面上等待超过 7 分钟。是的,这是我的应用程序所做的必不可少的。在你问为什么这需要这么长时间之前,这与 JSON 数据的结构有关。
简而言之,AKA 第一次请求获取数据点列表,然后对每个数据点分别进行第二次请求,因为详细信息的请求 url 在该数据点内。
在此后台进程的最后一步,邮件将通过发送网格发送,根据文件是否太大,它会发送一个带有特殊“本地文件”链接的附件以供下载。邮件的文本会根据情况有不同的内容,但您必须从中获得的主要内容是,无论文件是否作为附件,您将始终拥有本地文件“下载位置”。
import os
import base64
from datetime import datetime
from flask import Flask
import Classified.background_script.converter.GIPOD_Converter as data_conv
from flask import send_file, send_from_directory, safe_join, abort, render_template, jsonify
from Classified import app
from celery import Celery
import random
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import (
Mail, Attachment, FileContent, FileName,
FileType, Disposition, ContentId)
from sendgrid import SendGridAPIClient
import Classified.background_script.sendgrid as mail_delivery
send_grid_mail = 'Classified'
sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
app = Flask(__name__)
def main(file_name: str,file_location:str, attachment_bool: bool, download_link:str, recipient_email: str):
file_path = file_location
if os.getenv('SENDGRID_API_KEY') == None:
print("No API KEY FOUND")
else:
print("API KEY FOUND")
html_string = generate_html_content(attachment_bool,download_link)
message = Mail(
from_email='Classified',
to_emails=recipient_email,
subject='Uw data is gereed.',
html_content= html_string)
if attachment_bool is True:
with open(file_path, 'rb') as f:
data = f.read()
f.close()
encoded_file = base64.b64encode(data).decode()
attachment = Attachment()
attachment.file_content = FileContent(encoded_file)
attachment.file_type = FileType('application/zip')
attachment.file_name = FileName('.zip'.format(file_name))
attachment.disposition = Disposition('attachment')
attachment.content_id = ContentId('Example Content ID')
message.attachment = attachment
try:
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print("Failed scenario")
print("Scenerio checking")
# Generates the HTML variables for the email page.
def generate_html_content(attachment_bool: bool, download_link: str):
if attachment_bool is False:
Letter_1 = "Helaas was deze te groot om via mail door te sturen."
Letter_2 = "Klik hier om het bestand te downloaden."
if attachment_bool is True:
Letter_1 = "U vindt het bestand terug in de bijlage."
Letter_2 = "Is het bestand niet in de bijlage terug te vinden? Klik dan hier en download dan hier."
return render_template(
'email.html',
message_1 = Letter_1,
message_2 = Letter_2,
link = download_link,
title='YOU GOT MAIL'
)
if __name__ == "__main__":
main()
您可能会问我为什么要使用 html 页面渲染功能?好吧,因为以下原因
本质上,我是在渲染一个带有变量的静态模板
但是当它不是多进程时,我遇到了一个我没有遇到过的特定问题。
Traceback (most recent call last):
File "D:\IDE\Anaconda3\envs\PYTHONGDAL\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "D:\IDE\Anaconda3\envs\PYTHONGDAL\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "D:\Programmeer portfolio\FLASK\Classfiied\Classfiied\views.py", line 178, in execute_order66
Order66.main(stringpart,url,sper_year,email)
File "D:\Programmeer portfolio\FLASK\Classfiied\Classfiied\background_script\backgroundtask.py", line 53, in main
mail_delivery.main(file_name,requested_data,attachment_bool,requested_data,email)
File "D:\Programmeer portfolio\FLASK\Classfiied\Classfiied\background_script\sendgrid\send_mail.py", line 30, in main
html_string = generate_html_content(attachment_bool,download_link)
File "D:\Programmeer portfolio\FLASK\Classfiied\Classfiied\background_script\sendgrid\send_mail.py", line 67, in generate_html_content
return render_template(
File "D:\IDE\Anaconda3\envs\Classfiied\lib\site-packages\flask\templating.py", line 146, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
我不明白为什么会出现此错误,是我需要做一些特别的事情,还是我必须走不同的路线,并编写完整的 HTML?
【问题讨论】:
一些拼写错误。 A.K.A 是 known as 的缩写。虽然我的英语说得非常好(我的母语是荷兰语),但我通常会犯很多我忽略的拼写错误。我只是阅读了它们,即使在双重/三重检查时也是如此。 【参考方案1】:这里是 Twilio SendGrid 开发人员宣传员。
跟踪结束时的错误是:
File "D:\IDE\Anaconda3\envs\Classfiied\lib\site-packages\flask\templating.py", line 146, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
这告诉我ctx
对象在这里是NoneType
,它不应该是。我认为问题在于您在烧瓶应用程序的上下文之外运行此代码,它没有运行 Flask 路由来响应传入的 HTTP 请求,您只是将其作为常规函数调用。当它不是多进程时,我猜这是在 Flask 路由的上下文中运行的。
我查看了如何在 Flask 路由之外使用render_template
,最终遇到了these examples on Full Stack Python,特别是示例4,它使用render_template
呈现HTML,然后作为电子邮件发送。 example is from flask-base 并使用 with app.app_context()
在 Flask 应用程序的上下文中运行代码,而不是路由的一部分。
我通常不是 Python 程序员,但也许这样的东西适用于您的应用程序:
def generate_html_content(attachment_bool: bool, download_link: str):
if attachment_bool is False:
Letter_1 = "Helaas was deze te groot om via mail door te sturen."
Letter_2 = "Klik hier om het bestand te downloaden."
if attachment_bool is True:
Letter_1 = "U vindt het bestand terug in de bijlage."
Letter_2 = "Is het bestand niet in de bijlage terug te vinden? Klik dan hier en download dan hier."
with app.app_context():
return render_template(
'email.html',
message_1 = Letter_1,
message_2 = Letter_2,
link = download_link,
title='YOU GOT MAIL'
)
让我知道这是否有帮助。
【讨论】:
感谢您提供此信息,这实际上是问题所在,实际上我在您回答之前自己发现了它,我不得不将所有 HTML 单独编写到一个非 Flask 相关函数中,然后它就起作用了.我会把你的答案标记为正确的,谢谢。以上是关于Python烧瓶多进程:无法“呈现”用于发送网格电子邮件正文的html页面的主要内容,如果未能解决你的问题,请参考以下文章