【问题标题】:What does Thread Local Objects mean in Flask?Flask 中的线程局部对象是什么意思?
【发布时间】:2014-11-11 07:59:09
【问题描述】:

我正在阅读 Flask 文档(特别是 Foreword for Experienced Programmers chapter)并且我阅读了这个 -

Flask 的设计决策之一是简单的任务应该简单;他们不应该占用很多代码,但他们不应该限制你。正因为如此,Flask 的设计选择很少,有些人可能会感到惊讶或不正统。例如,Flask 在内部使用线程本地对象,因此您不必在请求中从一个函数到另一个函数传递对象以保持线程安全。这种方法很方便,但需要有效的请求上下文来进行依赖注入或尝试重用使用与请求挂钩的值的代码。 Flask 项目对线程局部变量是诚实的,不会隐藏它们,并在使用它们的代码和文档中调用。

这是什么意思?具体如下问题-

  • 什么是线程本地对象?它们的使用方式和时间以及它们的用途是什么?
  • 在内部使用线程局部对象如何确保线程安全以及将对象传递给函数如何导致线程不安全?
  • 在这种情况下,有效的请求上下文是什么意思?

【问题讨论】:

    标签: python flask


    【解决方案1】:

    线程本地对象是存储在专用结构中的对象,与当前线程 ID 相关联。如果您向该结构询问对象,它将使用当前线程标识符为您提供当前线程唯一的数据。见threading.local。您还可以通过在 Python 交互式解释器中输入 import _threading_local; help(_threading_local) 来获取更多详细信息。

    这意味着每当您使用current_appgrequests 时,您都会获得一个可以安全地在您的线程(或进程或 eventlet)中使用的数据结构,而无需担心锁定和其他问题并发问题。

    在正常操作中,Flask 处理传入的 WSGI 请求;对于每个此类请求,都会为您创建一个请求上下文;这由 grequest 对象表示。如果您尝试使用任何视图 没有传入请求(例如,在您的测试中),那么request 对象将不起作用并抱怨没有有效的请求上下文。 Flask 为您提供了在这种情况下按需生成此类上下文的工具。请参阅 Faking Resources and Context documentationRequest Context 章节。

    【讨论】:

    • 当用户在浏览器中输入flask URL,并且请求到达flask服务器时,flask服务器是否为每个URL请求启动一个新进程或一个新线程?每个进程/线程是否具有包含用户先前请求的 g、current_app 和 request 对象的请求上下文 - 这些请求存储在服务器上并根据用户请求发送的令牌进行解密?
    • @variable:如何处理并发取决于 WSGI 容器服务器,而不是 Flask 本身,例如如果你使用 Gunicorn,你可以configure the number of processes and threads 它会使用。每个请求都有一个 new current_apprequest 对象。其他代码,例如 Flask Session API 构建在此之上,可以执行诸如基于令牌加载数据之类的操作。那是完全分开的。
    • 我相信 Flask 也会调用 current_apprequest context locals,因为它们在单个线程上的每个请求之后都会被销毁(而不是线程本地,这意味着与线程具有相同的生命周期)。
    • @kennysong 是的,但是该功能的文档明确引用了线程本地概念,这个问题正在询问该概念。我的回答解决了所提出的问题,我没有在这里命名 Flask 上下文本地人。
    猜你喜欢
    • 1970-01-01
    • 2012-07-01
    • 2012-03-08
    • 2011-06-12
    相关资源
    最近更新 更多