Flask中的速度优化

Rol*_*Bly 4 html python jinja2 flask

我的项目(Python 2.7)包含一个屏幕抓取器,它每天收集一次数据,提取有用的内容并将其存储在几个泡菜中.使用Flask/Ninja将泡菜渲染为HTML页面.一切正常,但在我的localhost(Windows 10)上运行时,速度相当慢.我打算在PythonAnywhere上部署它.

该网站还有一个关于页面.about页面的内容是markdown文件,我markdown2在每次编辑后使用它转换为HTML .about-template加载HTML,如下所示:

{% include 'about_content.html' %}
Run Code Online (Sandbox Code Playgroud)

这比加载渲染about-text 快得多Flask-Markdown(就像我之前一样):

{% filter markdown %}
{% include 'about_content.md' %}
{% endfilter %}
Run Code Online (Sandbox Code Playgroud)

接着.我有点担心在部署网站时主页面加载速度不够快.内容每天只更新一次,如果刷新主页,则无需重新渲染任何内容.所以我想知道我是否可以使用与about-content类似的技巧:

在渲染泡菜之后,我可以让Flask将结果保存为html,然后从部署的站点提供服务吗?或者我可以调用某些浏览器模块,保存其输出并提供服务吗?或者这完全是一个坏主意,我不应该担心因为Flask在现实生活中的服务器上速度快吗?

Abh*_*pal 8

你的渲染问题

你可以用Jinja做很多事情.可以随时运行Jinja并将其另存为HTML文件.这样,每次发送文件请求时,都不必再次呈现它.它只是提供静态文件.

这是一些代码.我认为在整个生命周期中都没有改变.因此,一旦创建了视图,我就会创建一个静态HTML文件.

from jinja2 import Environment, FileSystemLoader

def example_function():
    '''Jinja templates are used to write to a new file instead of rendering when a request is received. Run this function whenever you need to create a static file'''

    # I tell Jinja to use the templates directory
    env = Environment(loader=FileSystemLoader('templates'))

    # Look for the results template
    template = env.get_template('results.html')

    # You just render it once. Pass in whatever values you need. 
    # I'll only be changing the title in this small example.
    output_from_parsed_template = template.render(title="Results")

    with open("/directory/where/you/want/to/save/index.html", 'w') as f:
        f.write(output_from_parsed_template)

# Flask route
@app.route('/directory/where/you/want/to/save/<path:path>')
def serve_static_file(path):
    return send_from_directory("directory/where/you/want/to/save/", path)
Run Code Online (Sandbox Code Playgroud)

现在,如果你去,上面的URI localhost:5000/directory/where/you/want/to/save/index.html服务没有渲染.

编辑注意,@app.route需要一个URL,所以/directory/where/you/want/to/save必须从根开始,否则你得到ValueError: urls must start with a leading slash.此外,您可以使用其他模板保存呈现的页面,然后按如下方式进行路由,从而无需(并且速度一样快)send_from_directory:

@app.route('/')
def index():
    return render_template('index.html')
Run Code Online (Sandbox Code Playgroud)

其他方法

如果您想获得更好的性能,请考虑通过gunicorn,nginx等提供Flask应用程序.

设置nginx,gunicorn和Flask

不要在生产中使用Flask

Flask还有一个选项,您可以在其中启用多线程.

app.run(threaded=True)
Run Code Online (Sandbox Code Playgroud)

更新于2018年11月11日

  • 您可以考虑使用Redis商店.每当发生使旧模板无效的事件时,请清除特定文件的缓存.在再次生成模板之前首先查看Redis存储(模板渲染很可能需要您从数据库中读取数据.内存缓存存储更快,因此您可以从Redis缓存中受益)
  • 存储渲染文件并使用CDN进行投放.因此,每次客户端请求该特定模板时,它都将存储在CDN上,并且根本不会触及Flask服务器.您可以编写逻辑,以便如果CDN上不存在文件或内容,它应该回退到Flask服务器.您只需确保策略,以便在CDN上没有陈旧数据.

  • 顺便说一句,我忘了提.切勿在真实服务器(生产)上使用Flask.Flask自己的创造者反对这个想法.烧瓶不安全,在现实生活中也不高效.如果要将其部署在生产环境中,请在Flask旁边使用gunicorn和nginx. (3认同)
  • 来自 PythonAnywhere 开发人员的简短说明(正如 OP 所说,他们计划在我们的网站上部署)——我们使用 nginx 作为我们的前端 Web 服务器,因此您的 Flask 应用程序是安全且高效的。 (2认同)