我(可能)很困惑。我想安全地创建 Flask/WSGI 应用程序 来自应用程序工厂,并且仍然能够轻松地在 WSGI 服务器中使用它们。
tl;博士
我能否安全地避免在导入 init 时创建应用程序(如 推荐)而不是稍后创建它(即使用工厂方法)
如何使该应用程序与 WSGI 服务器巧妙地协同工作?尤其 当我传入配置和其他设置时不拉动它们 来自环境
例如::
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
我想使用上面的“工厂”,因为我想轻松地控制配置以进行测试等。
然后我大概想创建一个 wsgi.py 模块,将应用程序提供给 WSGI 服务器。
所以最终事情看起来有点像这样
初始化.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
wsgi.py::
from mypackage import app
app = make_app(configfromsomewhere, "myname")
uWSGI::
uwsgi --module=mypackage.wsgi:app
但是 wsgi.py 仍然不是我可以调用的 wsgi.py --settings=x --host=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.
re: 2.,很明显,路由装饰器期望从中获得某些能力 一个实例化的应用程序,没有它们就无法运行。没关系。
回复:1.,好的,我们需要正确的名称。但什么是不安全的?和 为什么?如果应用程序未初始化,导入和使用是否不安全? 好吧,它会破裂,但这并非不安全。 它是备受吹捧的线程本地吗?可能吧。但如果我正在采摘 来自随机模块的应用程序实例,我应该预料到会有麻烦。
含义 - 除了 View 之外,我们不从任何其他地方引用应用程序对象 - 本质上我们保持我们的模块化很好和紧密,并传递 指令、错误对象,甚至 WebOb。
http://flask.pocoo.org/docs/patterns/appdispatch http://flask.pocoo.org/docs/deploying/#deployment http://flask.pocoo.org/docs/patterns/packages/#larger-applications http://flask.pocoo.org/docs/becomingbig
最佳答案
根据Flask Documentation ,应用程序工厂是好的,因为:
Testing. You can have instances of the application with different settings to test every case.
Multiple instances. Imagine you want to run different versions of the same application. Of course you could have multiple instances with different configs set up in your webserver, but if you use factories, you can have multiple instances of the same application running in the same application process which can be handy.
但是,正如 Other Testing Tricks 中所述文档部分,如果您使用应用程序工厂,函数 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)
现在您需要一个文件来创建应用程序的实例:
from yourapplication import create_app
app = create_app()
if __name__ == "__main__":
app.run()
在上面的代码中,我假设有一个环境变量设置了配置文件的路径,但您可以将配置路径提供给工厂,如下所示:
app = create_app('config/prod.cfg')
或者,您可以使用带有环境和相应配置文件的字典之类的东西:
CONFIG_FILES = {'development': 'config/development.cfg',
'test' : 'config/test.cfg',
'production' : 'config/production.cfg' }
在这种情况下,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])
这是 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;
}
}
uWSGI 配置文件如下所示:
[uwsgi]
plugins=python
vhost=true
socket=/tmp/yourapplication.sock
env = YOURAPPLICATION_ENV=production
logto = /var/www/yourapplication/logs/uwsgi.log
before_request()和after_request()这些函数的问题在于,如果您在其他模块中调用它们,则在实例化应用程序之前无法导入这些模块。同样,documentation对此有话要说:
The downside is that you cannot use the application object in the blueprints at import time. You can however use it from within a request. How do you get access to the application with the config? Use 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'])
或者您可以考虑 creating an extension ,那么您可以在没有任何 Flask 实例的情况下导入类,因为类扩展只会在创建后使用 Flask 实例。
关于python - 我如何在 Flask/WSGI 服务器中使用应用程序工厂,为什么它可能不安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13751277/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack