22

How can I set a request timeout using Python Flask? I'm trying to compare Flask to some other framework and need to configure the timeouts to be equivalent.

Thanks!

user2395365
  • 1,991
  • 4
  • 18
  • 34
  • 3
    What timeouts are you referring to? Flask itself doesn't actually handle network connections; that's left to the WSGI server you run it on. There is a simple WSGI server included to run while developing, but there is little point in benchmarking *that*. – Martijn Pieters Apr 18 '14 at 13:01

3 Answers3

9

As Martijn Pieters said in their comment on the question, this isn't something you want to do because the Flask development server isn't a good choice for production. It would be better to run your flask application on a server like Gunicorn and set the timeout there instead.

But to answer the question anyway, Flask.run has an options parameter allowing you to pass options through to the underlying Werkzeug server:

run(host=None, port=None, debug=None, load_dotenv=True, **options)

The relevant werkzeug method in turn has a request_handler parameter allowing you to specify what request handler is to be used:

werkzeug.serving.run_simple(hostname,
    port,
    application,
    use_reloader=False,
    use_debugger=False,
    use_evalex=True,
    extra_files=None,
    reloader_interval=1,
    reloader_type='auto',
    threaded=False,
    processes=1,
    request_handler=None,
    static_files=None,
    passthrough_errors=False,
    ssl_context=None
)

This is your hook for supplying a request handler object that implements the timeout policy you want (a subject explored in this question: How to implement Timeout in BaseHTTPServer.BaseHTTPRequestHandler Python).

Harry Moreno
  • 10,231
  • 7
  • 64
  • 116
Tommy Herbert
  • 20,407
  • 14
  • 52
  • 57
5

WSGI server

WSGI is the protocol, a facade separating your code from the actual web server which runs it.

In the flask, you only create the logic of the server. On run, your Flask application is served by the WSGI server. The most common is uWSGI ( & nGinx proxy to the secure border between the outer world and your server). But you can use whichever WSGI server suits you best without need to change your code (nichol.as/benchmark-of-python-web-servers)*.

Flask itself ships only with the Development WSGI flask server. It means the server uses a lot of features to help the developer debug their application. These features make the server very slow. So when you do a benchmark of your app on the Development WSGI flask server, results have no value for you.

On the other hand, specialized production-ready WSGI servers (including uWSGI) are well optimized, tested and production-proven. Most of the features are usually turned off by default and allow you to fine-tune these powerful beasts for your application.

Deployment tutorials:

Timeout

Now when I explained the context, back to your original question. I would set requests timeout in your:

  1. test client :
import requests
requests.get('https://api.myapp.com', timeout=3)
<Response [200]>
  1. nGinx proxy cofing:
http
{
  server
  {
    …
    location /
    {
         …
         proxy_read_timeout 120s;
        …
    }
  }
}
Ryu_CZ
  • 125
  • 2
  • 10
  • 14
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Sasa Nov 06 '14 at 08:33
  • @Ryu_CZ I completely agree that Flask application should be server by WSGI server. But I think Flask itself is able to servers multiple requests at same time if app.run() has "threaded=true" option. I want to know what you said exactly because I'm now facing performance issue. I'm setting up WSGI server. – zono May 16 '18 at 16:05
  • @zono wsgi.multithread This value should evaluate true if the application object may be simultaneously invoked by another thread in the same process, and should evaluate false otherwise. wsgi.multiprocess This value should evaluate true if an equivalent application object may be simultaneously invoked by another process, and should evaluate false otherwise. – Ryu_CZ May 19 '18 at 07:25
3

If the question is related to the Flask timeout while waiting for the completion of the browser data request after a TCP socket connection is set-up by the browser and accepted by Flask (i.e., werkzeug, where each line sent by the browser resets the timer), a trivial solution would be to add this before app.run(...):

import socket
socket.setdefaulttimeout(10) # seconds

Setting it once at the beginning of the program affects all new socket connections.

A timed out request generates the BaseHTTPRequestHandler error Request timed out: TimeoutError('timed out').

This configuration does not appear to control the time Flask takes to process a valid request, which should be implemented inside the function decorated with @app.route(...).

ircama
  • 75
  • 1
  • 5