Я отправляю письма из своего приложения Flask с расширением Flask-Mail. Он запускает метод send() синхронно, и я должен ждать, пока он отправит сообщение. Как я могу запустить его в фоновом режиме?Асинхронный запуск Flask-Mail
ответ
Это не так сложно - вам нужно отправить почту в другой поток, так что вы не будете блокировать основной поток. Но есть один трюк.
Вот мой код, который делает шаблон, создание почтового тела, и позволяет отправлять его как синхронно, так и асинхронно:
mail_sender.py
import threading
from flask import render_template, copy_current_request_context, current_app
from flask_mail import Mail, Message
mail = Mail()
def create_massege(to_email, subject, template, from_email=None, **kwargs):
if not from_email:
from_email = current_app.config['ROBOT_EMAIL']
if not to_email:
raise ValueError('Target email not defined.')
body = render_template(template, site_name=current_app.config['SITE_NAME'], **kwargs)
subject = subject.encode('utf-8')
body = body.encode('utf-8')
return Message(subject, [to_email], body, sender=from_email)
def send(to_email, subject, template, from_email=None, **kwargs):
message = create_massege(to_email, subject, template, from_email, **kwargs)
mail.send(message)
def send_async(to_email, subject, template, from_email=None, **kwargs):
message = create_massege(to_email, subject, template, from_email, **kwargs)
@copy_current_request_context
def send_message(message):
mail.send(message)
sender = threading.Thread(name='mail_sender', target=send_message, args=(message,))
sender.start()
Обратите внимание на @copy_current_request_context
декоратора. Это необходимо, потому что Flask-Mail внутри использует контекст запроса. Если мы запустим его в новом потоке, контекст будет пропущен. Мы можем предотвратить эту функцию украшения с помощью @copy_current_request_context
- Flask будет вызывать контекст при вызове функции.
Чтобы использовать этот код вам также необходимо инициализировать mail
объект с приложением Колба:
run.py
app = Flask('app')
mail_sender.mail.init_app(app)
Действительно полезный! благодаря! –
Я хотел бы, чтобы упростить код Marboni в так смотрите здесь.
import threading
from flask import copy_current_request_context
from flask_mail import Message
from app import app, mail
def create_message(recipient, subject, body):
if not recipient:
raise ValueError('Target email not defined.')
subject = subject.encode('utf-8')
body = body.encode('utf-8')
return Message(subject, [recipient], body, sender=app.config['MAIL_USERNAME'] or "[email protected]")
def send_async(recipient, subject, body):
message = create_message(recipient, subject, body)
@copy_current_request_context
def send_message(message):
mail.send(message)
sender = threading.Thread(name='mail_sender', target=send_message, args=(message,))
sender.start()
Возможный дубликат [это] (http://stackoverflow.com/questions/10003933/whats-the-proper-way-to-run-some-python-code-asynchronously) – Enrico