想用新线程装饰电子邮件发送

时间:2014-10-06 21:48:31

标签: python multithreading flask

我坚持装饰这个功能。 帮我找出问题所在。 装饰器:

def sync(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper

发送功能:

def send_email(subject, sender, recipients, text_body, html_body):
    """ Build and send e-mail with the provided parameters."""

    msg = Message(subject, sender=sender, recipients=recipients)
    msg.body = text_body
    msg.html = html_body
    mail.send(msg)

@sync
def send_confirmation_email(recipient, app = current_app):
    """Send registration email to the provided recipient."""

    subject = 'Account confirmation e-mail'
    sender = 'some.mail.for.testing@domain.com'
    recipients = [recipient]
    activation, deletion = confirmation_links(recipient) #construct hashed links
    text_body = render_template('confirmation_email.txt',
                            activation = activation,
                            deletion = deletion)
    html_body = render_template('confirmation_email.html',
                            activation = activation,
                            deletion = deletion)
    send_email(subject, sender, recipients, text_body, html_body)

观看功能:

@app.route('/signup', methods = ['GET', 'POST'])
def signup():
    form = SignupForm()
    if form.validate_on_submit():
        send_confirmation_email(recipient = form.email.data)
        return redirect(url_for('activate'))
    else:
        return render_template('signup.html',
                       title = 'Sign Up',
                       form = form)

问题是电子邮件不会与活动装饰器@sync一起发送。 当我删除@sync装饰器时,一切正常,但当然没有线程。 并且appredirect之前等待几秒钟。 任何帮助都会有所帮助。感谢。

1 个答案:

答案 0 :(得分:2)

render_template功能需要Flask application context才能正常工作。

当您的send_confirmation_email函数在单独的线程中运行时,没有为render_template设置应用程序上下文。

您可以使用app.app_context()

解决此问题
@sync
def send_confirmation_email(recipient):
    """Send registration email to the provided recipient."""

    with app.app_context():
        subject = 'Account confirmation e-mail'
        sender = 'some.mail.for.testing@domain.com'
        recipients = [recipient]
        activation, deletion = confirmation_links(recipient) #construct hashed links
        text_body = render_template('confirmation_email.txt',
                                activation = activation,
                                deletion = deletion)
        html_body = render_template('confirmation_email.html',
                                activation = activation,
                                deletion = deletion)
        send_email(subject, sender, recipients, text_body, html_body)

您还可以考虑使用Celery

之类的内容