Flask中的速度优化

时间:2016-09-30 09:52:03

标签: python html flask jinja2

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

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

{% include 'about_content.html' %}

这比<{1}}渲染about-text更快地加载 (就像我最初那样):

Flask-Markdown

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

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

1 个答案:

答案 0 :(得分:7)

您的渲染问题

你可以用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)

现在如果你去了上面的URI localhost:5000/directory/where/you/want/to/save/index.html没有渲染就可以了。

编辑请注意,@app.route需要一个网址,因此/directory/where/you/want/to/save必须从根开始,否则您会获得ValueError: urls must start with a leading slash。此外,您可以使用其他模板保存呈现的页面,然后按照以下方式进行路由,从而无需({和1}} {<1}}一样快:

send_from_directory

其他方式

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

Setting up nginx, gunicorn and Flask

Don't use Flask in production

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

@app.route('/')
def index():
    return render_template('index.html')

2018年11月11日更新

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