13

考虑我在 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

这些也会随着请求而增加

4

3 回答 3

17

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

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

于 2011-11-18T01:50:22.860 回答
5

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

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

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

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

于 2011-11-17T17:07:06.750 回答
2

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

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

于 2011-11-27T02:16:21.830 回答