Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

number of threads in flask

i just learn about flask and requests. i want to get the number of working threads when i post request to the server. and i want to measure the time spent of the working threads. so this is my server and my client code:

server.py

from flask import Flask
from flask import request
import time 
from flaskthreads import AppContextThread

app = Flask(__name__)

@app.route("/", methods = ['GET', 'POST'])

def home():
    timeout = time.time() + 10   # 5 minutes from now

    while True:
        test = 0
        if test ==5 or time.time() > timeout:
            break 

    return 'Hello', 200

def main():
    app.run(host='0.0.0.0', threaded = True, debug = True)


if __name__ == "__main__":
    main()

client.py

import os
import requests
import glob
import time 
import base64


url = 'http://0.0.0.0:5000/'


def load_data():

    os.chdir('./500_mb')
    for image in glob.glob('*.jpg'):
        with open(image, 'rb') as imageFile:
            # image_s = base64.b64encode(imageFile.read())
            image_s = {'file_image':open(image, 'rb')}

    return image_s

def send_data():

    start = time.time()
    r = requests.post(url, files = load_data())
    end = time.time()

    print('client 1: {} ms'.format((end - start)*1000))



if __name__ == "__main__":
    send_data()

how do i know the number of working threads ? i just add threaded = True on the server. i've been searching the answer and none of them answer my question. thanks in advance !

like image 265
Farhan Rabbaanii Avatar asked Dec 13 '19 10:12

Farhan Rabbaanii


People also ask

Is Flask single threaded?

As of Flask 1.0, flask server is multi-threaded by default. Each new request is handled in a new thread. This is a simple Flask application using default settings.

How much traffic can Flask handle?

Flask will process one request per thread at the same time. If you have 2 processes with 4 threads each, that's 8 concurrent requests. Flask doesn't spawn or manage threads or processes.

How many threads python can run?

Generally, Python only uses one thread to execute the set of written statements. This means that in python only one thread will be executed at a time.

What is threaded true in Flask?

With threaded=True requests are each handled in a new thread. How many threads your server can handle concurrently depends entirely on your OS and what limits it sets on the number of threads per process. The implementation uses the SocketServer.

What is threading in Python and flask?

The system was implemented in Pythons web micro-framework Flask. Threading in Python is simple. It allows you to manage concurrent threads doing work at the same time. The library is called “ threading “, you create “Thread” objects, and they run target functions for you. You can start potentially hundreds of threads that will operate in parallel.

How to solve multi-threading issues in flask?

For a multi-threaded request, it’s unclear which Request object is used at the moment. If there are some changes to be made on certain request, it can’t be guaranteed that the targeted request instance is changed, which results in contaminated data. To solve the issues of multi-threading in Flask we can use dictionary data structure, e.g.

How to access current application context from another thread in flask?

The most common scenario is to try to access flask.g object. Application context is a thread local so you can not access it from another thread and Flask will raise an exception if you would try to. This library provides helper classes that allows you accessing the current application context from another thread.

How many threads should I start for each task?

This method of starting one thread for each task will work well unless you have a high number (many hundreds) of tasks to complete. The solution outlined above operated successfully for us, with users to our web application requiring, on average, 9-11 threads per request.


1 Answers

First of all, the usual disclaimer: This is pretty much irrelevant because you would be able to specify this when you actually move to a deployment server.

However, I was curious myself, so I decided to trace this back.

The starting point is in app.run() so let's look at what that does:

def run_command(
    info, host, port, reload, debugger, eager_loading, with_threads, cert, extra_files
):

...

from werkzeug.serving import run_simple

    run_simple(
        host,
        port,
        app,
        use_reloader=reload,
        use_debugger=debugger,
        threaded=with_threads,
        ssl_context=cert,
        extra_files=extra_files,
    )

So, next port-of-call is werkzeug.serving with run_simple.

From here, you'll be buffeted about the module:

  1. First you'll see that this uses make_server
  2. make_server launches ThreadedWSGIServer
  3. ThreadedWSGIServer takes socketserver.ThreadingMixIn as an argument.

Head over to socketserver. We can see from the source code the following:

class ThreadingMixIn:
    """Mix-in class to handle each request in a new thread."""

    ...

    def process_request(self, request, client_address):
        """Start a new thread to process the request."""
        t = threading.Thread(target = self.process_request_thread,
                             args = (request, client_address))
        t.daemon = self.daemon_threads
        if not t.daemon and self.block_on_close:
            if self._threads is None:
                self._threads = []
            self._threads.append(t)
        t.start()

So, the answer is that it launches a new thread on each request. If nothing else, it's an interesting exercise in tracing code paths.


Edit in Sept 2021: I originally made the mistake of not getting permalinks from git, so different parts of the answer went out of sync with the code paths I was trying to show. I've since corrected that to try be more stable with permalinks but, with several libraries involved, do note that things could change at any time. I think the general principle will hold for a while, though.

like image 118
roganjosh Avatar answered Oct 14 '22 11:10

roganjosh