我正在使用Flask构建我的Web应用程序,并且我想注册一个全局资源,该资源表示与远程服务的连接,该服务的持续时间超过请求(在这种情况下,连接是SOAP连接,有效期最长可达30天。)
另一个例子可能是像MongoDB这样的数据库,它处理驱动程序中的连接池,如果你在每个请求上创建了一个新的连接,它会表现不佳。
应用程序上下文和请求上下文都不适合此任务。
问题“Pass another object to the main flask application”表示我们会将这些资源存储在app.config
词典中。
答案 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技巧,如容器管理的并发....