【问题标题】:Understanding global object persistence in Python WSGI apps了解 Python WSGI 应用程序中的全局对象持久性
【发布时间】:2011-12-31 12:59:30
【问题描述】:

在我的 Google App Engine 中的 WebApp2 应用程序中考虑以下代码:

count = 0

class MyHandler(webapp2.RequestHandler):

    def get(self):

        global count
        count = count + 1
        print count

每次刷新页面时,计数都会增加。

我来自 PHP 世界,每个请求都是一个新的全局环境。我理解这里发生的是,因为我使用 WebApp2 的 wsgi 配置,Python 不会在每个请求上启动一个新进程。另一方面,如果我使用 cgi 配置,全局环境每次都会重新实例化,就像 PHP...

假设以上是正确的(如果不是,请纠正我)...

  1. 如何处理我希望全局变量仅在请求的生命周期内持续存在的情况?我可以在 RequestHandler 类中放置一个实例变量,但是我导入的实用程序模块之类的东西如何使用全局变量来存储消息对象?
  2. 是否有某种技术可以重置所有变量或强制重新实例化环境?
  3. 全球环境会无限期地持续下去,还是会在某个时候自行重置?
  4. 此 GAE 是否特定于任何一个,或者 wsgi 全局持久性在任何服务器场景中的工作方式都相同?

编辑:

这是使用 threadlocal 的尝试:

count = 0

mydata = threading.local()
mydata.count = 0

class MyHandler(webapp2.RequestHandler):

    def get(self):

        global count
        count = count + 1
        print count

        mydata.count = mydata.count + 1
        print mydata.count

这些也会随着请求而增加

【问题讨论】:

标签: python google-app-engine wsgi webapp2


【解决方案1】:

您对情况的分析是正确的,Python Web 应用程序是一个长期运行的过程。启动 Python 解释器需要很长时间,而且不是每次请求都完成。

创建一个“每个请求”不同的全局变量是完全可能的。这是在很多框架中完成的,人们似乎喜欢它。执行此操作的方法确实取决于服务器。大多数服务器使用“每个请求一个线程”,我认为 GAE 也是如此。如果是这种情况,您可以使用threadlocal variable。如果您担心该值在该线程上的请求之间存在,您将需要一些可以挂钩到请求的开始/结束的管理代码。如果 WebApp2 框架没有提供很好的方法来做这件事,WSGI 中间件是一个很好的地方。

它只是 Python,请求在它自己的线程中提供服务。从那里你可以做你想做的事。 Python 中没有任何东西可以重置所有全局变量,并且通常无法保证(尤其是使用 GAE)为您的请求提供服务的进程每次都是相同的进程,这意味着您的全局变量不应该用于在请求之间持久化数据,除非您真的知道你在做什么。

已经有许多框架为这样做提供了很好的支持,所以如果 WebApp2 没有,那么我建议寻找其他地方。 Python 有很多选择,其中很多都可以在 GAE 上运行。

【讨论】:

  • 谢谢。你能看看我的编辑吗?我试过 threading.local(),但这个计数就像我的全局一样递增。我执行对了吗?
  • 您的请求可能来自同一个线程。大多数 WSGI 服务器都是使用线程池实现的,因此每个请求不一定是 new 线程。我也不熟悉 GAE 如何为 WSGI 应用程序提供服务的内部工作原理,但这是我所期望的。
【解决方案2】:

你的理解是正确的。如果您希望变量在请求期间持续存在,则根本不应该将它们设为全局变量 - 在 RequestHandler 类中将它们设为实例变量,以self.var 访问。由于为每个请求都实例化了一个新的 RequestHandler,因此您的变量将在您需要时一直存在。除非您确实需要全局(而不是特定于请求)范围,否则最好避免使用全局变量。

另请注意,您的 App Engine 应用将在多个服务器上运行;全局变量只能被同一服务器内的请求访问。

【讨论】:

    【解决方案3】:

    对于您的第一个问题,我认为您可能会考虑使用webapp2.Request.registry 功能。这是一个存储不同模块在请求生命周期内可以共享的实例的字典。

    另一方面,webapp2.WSGIApplication.registry 也很有用。在这种情况下,实例会在请求之间持续存在,并且可以在应用程序的生命周期内为您的应用程序需要的任何内容共享(和重用),从而避免在全局范围内创建实例。

    【讨论】:

      猜你喜欢
      • 2011-10-08
      • 2016-09-27
      • 2011-12-18
      • 2012-03-29
      • 2016-03-14
      • 2010-09-24
      • 1970-01-01
      • 2017-10-19
      • 2021-04-23
      相关资源
      最近更新 更多