Speed optimisation in Flask
<p>My project (Python 2.7) consists of a screen scraper that collects data once a day, extracts what is useful and stores that in a couple of pickles. The pickles are rendered to an HTML-page using Flask/Ninja. All that works, but when running it on my localhost (Windows 10), it's rather slow. I plan to deploy it on PythonAnywhere. </p>

<p>The site also has an about page. Content for the about page is a markdown file, that I convert to HTML using <code>markdown2</code> after each edit. The about-template loads the HTML, like so: </p>

<pre><code>{% include 'about_content.html' %}
</code></pre>

<p>This loads <em>much</em> faster than letting <code>Flask-Markdown</code> render the about-text (as I had at first): </p>

<pre><code>{% filter markdown %}
{% include 'about_content.md' %}
{% endfilter %}
</code></pre>

<p>Now then. I'm a bit worried that the main page will not load fast enough when I deploy the site. The content gets updated only once a day, there is no need to re-render anything if you refresh the main page. So I'm wondering if I can do a similar trick as with the about-content:  </p>

<p>Can I let Flask, after rendering the pickles, save the result as html, and then serve that from the site deployed? Or can I invoke some browser module, save its output, and serve that? Or is that a bad idea altogether, and shouldn't I worry because Flask is zoomingly fast on real life servers? </p>

<h2>Your Question on Rendering</h2>

<p>You can actually do a lot with Jinja. It is possible to run Jinja whenever you want and save it as a HTML file. This way every time you send a request for a file, it doesn't have to render it again. It just serves the static file.</p>

<p>Here is some code. I have a view that doesn't change throughout it's lifetime. So I create a static HTML file once the view is created.</p>

<pre><code>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/&lt;path:path&gt;')
def serve_static_file(path):
    return send_from_directory("directory/where/you/want/to/save/", path)
</code></pre>

<p>Now if you go the above URI <code>localhost:5000/directory/where/you/want/to/save/index.html</code> is served without rendering. </p>

<p><strong>EDIT</strong> Note that <code>@app.route</code> takes a URL, so <code>/directory/where/you/want/to/save</code> must start at the root, otherwise you get <code>ValueError: urls must start with a leading slash</code>. Also, you can save the rendered page with the other templates, and then route it as below, eliminating the need for (and it's just as fast as) <code>send_from_directory</code>:</p>

<pre><code>@app.route('/')
def index():
    return render_template('index.html')
</code></pre>

<h2>Other Ways</h2>

<p>If you want to get better performance consider serving your Flask app via <em>gunicorn, nginx and the likes.</em>  </p>

<p><a href="https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-14-04" rel="nofollow">Setting up nginx, gunicorn and  Flask</a>  </p>

<p><a href="http://stackoverflow.com/questions/33086555/why-shouldnt-flask-be-deployed-with-the-built-in-server">Don't use Flask in production</a></p>

<p>Flask also has an option where you can enable multi threading. </p>

<pre><code>app.run(threaded=True)
</code></pre>

python html flask ninja