Python flask multiprocess: 不能 "render" 发送网格电子邮件正文的 html 页面

Python flask multiprocess: cannot "render" a html page for the send grid email body

好的,我有一些重要的特定功能,即 运行 在后台作为多进程。又名第二个过程(以后可能更多)。

这样做的原因是它将重定向到一个 html 页面,说明请求已成功。 毕竟,在他的数据请求通过并转换数据之前,客户不会在加载页面上等待超过 7 分钟。是的,这是我的应用程序的基本功能。在您问为什么这需要这么长时间之前,这与 JSON 数据的结构有关。

简而言之,AKA 执行第一个请求以获取数据点列表,然后分别对每个数据点执行第二个请求,因为详细信息的请求 url 在该数据点内。

在此后台进程的最后一步,将通过发送网格发送邮件,并根据文件是否过大发送带有特殊“本地文件”的附件 link下载它。邮件的文本会根据情况有不同的内容,但你必须从中拿走的主要内容是文件是否作为附件,你将始终拥有本地文件“下载位置”。

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?

此处为 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 应用程序的上下文之外 运行ning 这段代码,它不是 运行ning Flask 路由以响应传入的 HTTP 请求,你只是调用它作为常规功能。当它不是多进程时,我猜这个 运行 在 Flask 路由的上下文中。

我查看了如何在 Flask 路由之外使用 render_template 并最终遇到了 these examples on Full Stack Python, particularly example 4, which used render_template to render HTML that is then sent as an email. That 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'
      )

如果有帮助请告诉我。