Skip to content

Instantly share code, notes, and snippets.

@lost-theory
Created January 12, 2013 23:49
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save lost-theory/4521102 to your computer and use it in GitHub Desktop.
Save lost-theory/4521102 to your computer and use it in GitHub Desktop.
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
Copy link

Super smart solution!

@chrickso
Copy link

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
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
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
Copy link

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

@joost823
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
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 :)

@mallikharjuna160003
Copy link

I got jinja2.exceptions.TemplateNotFound

@mallikharjuna160003
Copy link

please resolve this

@anddoellinger
Copy link

@mallikharjuna160003 To resolve this error just create a directory "templates" and put the required html files in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment