Flask长期存在全球资源

时间:2013-10-23 16:14:05

标签: python flask

我正在使用Flask构建我的Web应用程序,并且我想注册一个全局资源,该资源表示与远程服务的连接,该服务的持续时间超过请求(在这种情况下,连接是SOAP连接,有效期最长可达30天。)

另一个例子可能是像MongoDB这样的数据库,它处理驱动程序中的连接池,如果你在每个请求上创建了一个新的连接,它会表现不佳。

应用程序上下文和请求上下文都不适合此任务。

问题“Pass another object to the main flask application”表示我们会将这些资源存储在app.config词典中。

2 个答案:

答案 0 :(得分:5)

如果它必须与你的应用程序的实例化一致,那么你应该继承Flask。如果所有操作都将资源附加到对象上,考虑到创建应用程序是一个过程,这实际上并没有做很多事情。事实是,如果应用程序在实例化过程中不需要使用您的资源,则可能不需要这样做。

class MyApp(Flask):
    def __init__(self, *args, **kwargs):
        setattr(self, 'some_resource', SomeResource())
        super(Flask, self).__init__(*args, **kwargs)

app = MyApp(__name__)
app.some_resource.do_something()

除非你有一些特定的用例,否则最好不要编写一个包装器类,将其转换为flask-extension,在模块级别创建它并将其存储在app.extensions上。

class MyExtensions(object):
    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.extensions['my_extension'] = SomeResource()

app = Flask(__name__)
my_extension = MyExtension(app)

然后,您可以选择是否要为每个应用程序提供自己的资源(如上所述),或者您是否更愿意使用始终指向当前应用程序的共享资源

from flask import _request_ctx_stack
try:
    from flask import _app_ctx_stack
except ImportError:
    _app_ctx_stack = None

stack = _app_ctx_stack or _request_ctx_stack

class SomeResource(object):
    def do_something(self):
        ctx = stack.top
        app = ctx.app
my_resource = SomeResource()
my_resource.do_something()

我认为您不希望将它存储在应用程序上下文中,因为“它在实例化Flask对象时启动,并在第一个请求进入时隐式结束”

相反,您希望在模块级别创建资源。然后你可以将它作为扩展名附加到应用程序,或者是,甚至在配置中 - 尽管从它中快速扩展它会更加一致和合乎逻辑。

答案 1 :(得分:0)

这是一个Python问题,Flask和其他Web框架不允许这样做/使其非常困​​难的原因是因为没有为并发定义的​​内存模型。例如。假设您的网络服务器在他们自己的进程中提供请求(例如Gunicorn)。这将导致进程分离主进程,从而复制“全局”变量。如果你在Windows上运行一个服务器,那么由于缺少一个fork,它将改为创建一个重新导入所有模块的新进程,可能会生成一个全局状态的干净版本,它不记得在主进程中对它进行的任何更改-线。如果你在名字守卫身后宣布它,或者根本找不到它。

只有两种可能的方法可以始终如一地“正确”地做到这一点。一种是专门构建一个webapp来保存你的全局状态,并且只限于一个线程,并从这个webapp中获得你的另一个webapp调用状态。

第二,是使用Jython +线程。由于Jython在JVM中运行,因此它具有一个具有共享状态的良好定义的内存模型,因此您可以使用所有Java EE技巧,如容器管理的并发....