ホームページ  >  に質問  >  本文

python - flask中current_app._get_current_object()与current_app有什么区别?

在学习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.

看了这个我还是没懂书中的代码为什么要这样= =。。。

伊谢尔伦伊谢尔伦2721日前977

全員に返信(2)返信します

  • PHPz

    PHPz2017-04-17 18:01:56

    この質問の鍵は下から 3 番目の文にあります:

    リーリー

    ここで別のスレッドが開かれるのに、なぜスレッドを開いた後に current_app を使用できないのかと疑問に思われるかもしれません。右!スレッドを開くだけでは current_app は使用できません。その理由は current_app の実装にあります。

    current_appFlask のプロキシです。Flask のソース コードを見ると、実際には次のようにラップされていることがわかります:
    ソース コード アドレス行: 48-58

    リーリー

    この LocalProxy については詳しく説明しませんが、この LocalProxy の機能は、スレッド/コルーチンに従って、現在のコルーチン/スレッドに対応するオブジェクトを返すことであると言えます。

    と言う
    • スレッド A が A

    • を LocalProxy に挿入します
    • スレッド B が B を LocalProxy に挿入します

    どこにいても、

    • スレッド A は常に A を取得し、スレッド B は常に B を取得します

    これが、Flaskrequest のような変数を current_app のコード内で直接使用できる根本的な理由です。

    これが答えです。ここで新しいスレッドが開かれるため、実際のオブジェクトを通過しない場合、スレッド内で current_app を使用してもオブジェクトを取得できません。 flask 上下文がありません。これは Flask のもう 1 つの重要なコンセプトであり、言うことは多すぎます。

    質問者さんなら理解できるはずだと言えます。

    返事
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 18:01:56

    当時このコードを見て同じだと思いましたが、なぜ app=current_object ではないのでしょうか?

    それでは、もう一度見てください。私の言いたいことは、ドキュメント内の説明では、current_app がグローバル アプリケーション オブジェクトであり、current_app._get_current_object が get オブジェクト (オブジェクトの取得) であり、次のクラス Staticmethod と classmethod が対応するのと同様であるということです。異なるものです (この例えは正確ではありませんが、私が言いたいことを理解するのは難しくありません。本質的には非常に似ています)。

    この回答の説明を見てください:

    しかし、これを言うのは間違いです。_get_current_object

    の説明を見てください。

    現在のオブジェクトを返します。これは、パフォーマンス上の理由から、またはオブジェクトを別のコンテキストに渡したい場合に、一度にプロキシの背後にある実際のオブジェクトが必要な場合に便利です。

    ここに書いてあるのは実体です
    これはインスタンスということですか?このように理解することもできますし、もちろん、より正確にすることもできます。

    それがインスタンスであろうと、フレームワークを設計した人がそれを逆に書くことで変換できるので、何にしてもソースコードを見たほうが良いです。結局のところ、コードは人によって設計され、このフレームワークも人によって書かれます。あまりにもこだわることには意味がありません。オブジェクトかインスタンスか、最終的にはどちらでもないと思います。

    返事
    0
  • キャンセル返事