Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
flask: show request time in template
import time
from flask import Flask, request, g, render_template
app = Flask(__name__)
app.config['DEBUG'] = True
@app.before_request
def before_request():
g.request_start_time = time.time()
g.request_time = lambda: "%.5fs" % (time.time() - g.request_start_time)
@app.route("/")
def index():
t = request.values.get('t', 0)
time.sleep(float(t)) #just to show it works...
return render_template("index.html")
if __name__ == "__main__":
app.run(use_debugger=True, use_reloader=True)
Rendered in {{ g.request_time() }}
$ curl http://127.0.0.1:5000/
Rendered in 0.00100s
$ curl http://127.0.0.1:5000/?t=1
Rendered in 1.00106s
$ curl http://127.0.0.1:5000/?t=2
Rendered in 2.00111s
$ curl http://127.0.0.1:5000/?t=10
Rendered in 10.00057s
@cihantas

This comment has been minimized.

Copy link

cihantas commented Oct 20, 2016

Super smart solution!

@chrickso

This comment has been minimized.

Copy link

chrickso commented Feb 22, 2017

could you explain this a bit? what is the line g.request_time = lambda: "%.5fs" % (time.time() - g.request_start_time) doing exactly? i don't understand how you are coming up with a time if you are not doing anything during after_request

@arel

This comment has been minimized.

Copy link

arel commented Mar 6, 2017

@chrickso, that line just creates a function that returns the time since before_request was called. The function is called later when the template is rendered (in index.html) which happens after the request has completed.

@stestagg

This comment has been minimized.

Copy link

stestagg commented Sep 5, 2017

Given the lambda can capture the scope variables, you could simplify this to:

@app.before_request
def before_request():
    request_start_time = time.time()
    g.request_time = lambda: "%.5fs" % (time.time() - request_start_time)

unless, of course you want the request_start_time to be queryable separately

@hrytskivr

This comment has been minimized.

Copy link

hrytskivr commented Dec 15, 2017

Great, didn't know there's such thing as before_request and after_request, thank you :)

@joost823

This comment has been minimized.

Copy link

joost823 commented Jul 4, 2018

Cool solution, just one small thing to pay attention to when your measuring performance:

If you call {{ g.request_time() }} at the start of your html template, and then do a whole bunch of rendering, the time will be off. I had up to a factor of 20x speed difference, and couldn't figure out why, and this was the reason. My solution was to put this small snippet at the button of the template:

...

<p id="request_time_paragraph"></p>

do_some_heavy_rendering()
<script>
document.getElementById('request_time_paragraph').innerHTML = "{{ g.request_time() }}"
</script>
@horazont

This comment has been minimized.

Copy link

horazont commented Jun 27, 2019

You’ll want to use time.monotonic() for correctness :)

Otherwise, you end up with weird negative page rendering times during leap seconds :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.