在学习flask开发,书中一段异步发送邮件的代码是这样写的:
from threading import Thread
from flask import current_app, render_template
from flask.ext.mail import Message
from . import mail
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(to, subject, template, **kwargs):
app = current_app._get_current_object()
msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + ' ' + subject,
sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])
msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.html', **kwargs)
thr = Thread(target=send_async_email, args=[app, msg])
thr.start()
return thr
在send_mail
函数中,程序使用了current_app._get_current_object()
赋值给app
作为当前程序的实例。此处为什么不直接使用current_app
呢?
flask官方文档中是这样解释这个方法_get_current_object()
的:
Return the current object. This is useful if you want the real object behind the proxy at a time for performance reasons or because you want to pass the object into a different context.
看了这个我还是没懂书中的代码为什么要这样= =。。。
La clé de cette question réside dans la troisième phrase à partir du bas :
Parce qu'un fil de discussion séparé est ouvert ici, vous vous demandez peut-être pourquoi ne pouvez-vous pas utiliser
current_app
après avoir ouvert un fil de discussion ? droite! Ouvrez simplement un fil de discussion et vous ne pouvez pas utilisercurrent_app
. La raison réside dans la mise en œuvre decurrent_app
.
Je n'entrerai pas dans les détails à ce sujetcurrent_app
est un proxy dansFlask
Si vous regardez le code source deFlask
, vous constaterez qu'il est en fait enveloppé comme ceci :Ligne d'adresse du code source : 48-58
, mais je peux vous dire que la fonction de ceci
LocalProxy
est de renvoyer l'objet correspondant à la coroutine/thread actuelle en fonction du thread/coroutine, c'est-à-dire direLocalProxy
et
Donc, voici la réponse, car un nouveau fil est ouvert ici. Si vous ne passez pas par l'objet réel, alors vous ne pourrez pas obtenir l'objet si vous utilisezFlask
peuvent être utilisées directement dans le code derequest
.current_app
dans le fil, car il n'a pas
On peut dire que celui qui pose la question doit être capable de le comprendre.current_app
. C'est un autre concept important de Flask, il y a trop de choses à dire.flask 上下文
J'ai vu ce code à l'époque et j'ai pensé que c'était le même, mais pourquoi app=current_object ne peut-il pas être utilisé ?
Alors jetez un autre coup d'œil, ce que je veux dire est que la description dans le document mentionne que current_app est un objet d'application global et current_app._get_current_object est un objet get (obtenir un objet), similaire à la classe suivante Staticmethod et classmethod correspondent à des choses différentes (cette analogie n’est pas exacte, mais il n’est pas difficile de comprendre ce que je veux dire. Elles sont de nature très similaire).
Regardez l'explication de cette réponse :
Cependant, c'est faux de dire cela. Jetez un œil à l'explication de _get_current_object
Renvoyer l'objet actuel. Ceci est utile si vous voulez que l'objet réel soit derrière le proxy à la fois pour des raisons de performances ou parce que vous souhaitez passer l'objet dans un contexte différent.
Ce qui est écrit ici est un objet réel
Cela signifie-t-il qu'il s'agit d'une instance ? Cela peut être compris de cette façon, et bien sûr, cela peut être plus précis.
Parce que quoi qu'il arrive, il vaut mieux regarder le code source, car peu importe de quoi il s'agit, la personne qui a conçu le framework peut le convertir en l'écrivant à l'envers
Qu'il s'agisse d'une instance ou un objet, leurs méthodes seront certainement différentes. Après tout, le code est conçu par des personnes, et ce framework est également écrit par des personnes. Cela a plus à voir avec le framework lui-même. Cela n'a plus de sens d'être trop obsédé par les objets. ou des instances, car je suppose qu'en fin de compte, ce n'est ni l'un ni l'autre.