you*_*hat 11 python wsgi flask
我(可能)感到困惑.我想从app-factories安全地创建Flask/WSGI应用程序,并且仍然可以轻松地在WSGI服务器中使用它们.
TL;博士
我可以安全地避免在导入init时创建应用程序(如推荐的那样),而是稍后创建它(即使用工厂方法)
如何使该应用程序与WSGI服务器整齐地工作?特别是当我通过配置和其他设置而不是从ENV中拉出它们时
例如::
def make_app(configdict, appname):
app = Flask(appname)
app.config.update(configdict)
init_db(configdict)
set_app_in_global_namespace(app)
#importing now will allow from pkg import app
from mypackage import views
return app
Run Code Online (Sandbox Code Playgroud)
我想使用上面的"工厂",因为我想轻松控制配置进行测试等.
然后,我可能想要创建一个wsgi.py模块,该模块将应用程序提供给WSGI服务器.
所以事情看起来有点像这样
init .py ::
app = None
def make_app(configdict, appname):
flaskapp = Flask(appname)
flaskapp.config.update(configdict)
init_db(configdict)
global app
app = flaskapp
#importing now will allow from pkg import app
from mypackage import views
return flaskapp
Run Code Online (Sandbox Code Playgroud)
wsgi.py ::
from mypackage import app
app = make_app(configfromsomewhere, "myname")
Run Code Online (Sandbox Code Playgroud)
uWSGI ::
uwsgi --module=mypackage.wsgi:app
Run Code Online (Sandbox Code Playgroud)
但还是wsgi.py是不是我可以调用诸如wsgi.py --settings = X主机= 10.0.0.1所以,我真的不知道如何通过配置在.
我问,因为虽然这看起来......好吧......它也有点乱.
当一切都在ENV中时,生活变得更容易.
而且不仅是:
给出的建议here <http://flask.pocoo.org/docs/patterns/packages>_是::
1. the Flask application object creation has to be in the
__init__.py file. That way each module can import it safely and
the __name__ variable will resolve to the correct package.
2. all the view functions (the ones with a route() decorator on
top) have to be imported in the __init__.py file. Not the object
itself, but the module it is in. Import the view module after
the application object is created.
Run Code Online (Sandbox Code Playgroud)
re:2.显然路由装饰器需要来自实例化应用程序的某些功能,并且没有它们就无法运行.没关系.
re:1.,好的,我们需要正确的名称.但什么是不安全的?为什么?如果未初始化,导入和使用应用程序是否不安全?好吧它会破裂,但那并不安全.这是一个被大肆吹嘘的线程本地?有可能.但是,如果我从随机模块中挑选应用程序实例,我应该会遇到麻烦.
含义 - 我们不会从视图以外的任何内容引用app对象 - 基本上我们保持模块化的美观和严密,并传递dicts,错误对象甚至WebObs.
http://flask.pocoo.org/docs/patterns/appdispatch http://flask.pocoo.org/docs/deploying/#deployment http://flask.pocoo.org/docs/patterns/packages/#larger-应用程序 http://flask.pocoo.org/docs/becomingbig
may*_*din 24
根据Flask文档,应用工厂很好,因为:
测试.您可以使用不同设置的应用程序实例来测试每种情况.
多个实例.想象一下,您想要运行同一应用程序的不同版本.当然,您可以在Web服务器中设置多个具有不同配置的实例,但是如果您使用工厂,则可以在同一个应用程序进程中运行同一应用程序的多个实例,这样可以很方便.
但是,正如文档的" 其他测试技巧"部分所述,如果您正在使用应用程序工厂before_request(),after_request()则不会自动调用这些函数.
在接下来的段落中,我将展示我如何使用uWSGI应用程序服务器和nginx的应用程序工厂模式(我只使用了那些,但我可以尝试帮助您使用其他服务器配置它).
所以,让我们说你有文件夹里的应用程序yourapplication和里面那里的__init__.py文件:
import os
from flask import Flask
def create_app(cfg=None):
app = Flask(__name__)
load_config(app, cfg)
# import all route modules
# and register blueprints
return app
def load_config(app, cfg):
# Load a default configuration file
app.config.from_pyfile('config/default.cfg')
# If cfg is empty try to load config file from environment variable
if cfg is None and 'YOURAPPLICATION_CFG' in os.environ:
cfg = os.environ['YOURAPPLICATION_CFG']
if cfg is not None:
app.config.from_pyfile(cfg)
Run Code Online (Sandbox Code Playgroud)
现在您需要一个文件来创建应用程序的实例:
from yourapplication import create_app
app = create_app()
if __name__ == "__main__":
app.run()
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我假设有一个环境变量设置了配置文件的路径,但你可以给出工厂的配置路径,如下所示:
app = create_app('config/prod.cfg')
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用包含环境和相应配置文件的字典:
CONFIG_FILES = {'development': 'config/development.cfg',
'test' : 'config/test.cfg',
'production' : 'config/production.cfg' }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,load_config函数将如下所示:
def load_config(app, env):
app.config.from_pyfile('config/default.cfg')
var = "YOURAPPLICATION_ENV"
if env is None and var in os.environ:
env = os.environ[var]
if env in CONFIG_FILES:
app.config.from_pyfile(CONFIG_FILES[env])
Run Code Online (Sandbox Code Playgroud)
以下是nginx配置文件的示例:
server {
listen 80;
server_name yourapplication.com;
access_log /var/www/yourapplication/logs/access.log;
error_log /var/www/yourapplication/logs/error.log;
location / {
try_files $uri @flask;
}
location @flask {
include uwsgi_params;
uwsgi_pass unix:/tmp/yourapplication.sock;
# /env is the virtualenv directory
uwsgi_param UWSGI_PYHOME /var/www/yourapplication/env;
# the path where the module run is located
uwsgi_param UWSGI_CHDIR /var/www/yourapplication;
# the name of the module to be called
uwsgi_param UWSGI_MODULE run;
# the variable declared in the run module, an instance of Flask
uwsgi_param UWSGI_CALLABLE app;
}
}
Run Code Online (Sandbox Code Playgroud)
uWSGI配置文件如下所示:
[uwsgi]
plugins=python
vhost=true
socket=/tmp/yourapplication.sock
env = YOURAPPLICATION_ENV=production
logto = /var/www/yourapplication/logs/uwsgi.log
Run Code Online (Sandbox Code Playgroud)
before_request()和after_request()这些函数的问题在于,如果您在其他模块中调用它们,则在实例化应用程序之前无法导入这些模块.再次,文档有关于此的说法:
缺点是您无法在导入时在蓝图中使用应用程序对象.但是,您可以在请求中使用它.如何使用配置访问应用程序?使用current_app:
from flask import current_app, Blueprint, render_template
admin = Blueprint('admin', __name__, url_prefix='/admin')
@admin.route('/')
def index():
return render_template(current_app.config['INDEX_TEMPLATE'])
Run Code Online (Sandbox Code Playgroud)
或者你可以考虑创建一个扩展,然后你可以导入没有任何Flask实例的类,因为类扩展只会在创建后使用Flask实例.