Florian Bord
Florian Bord

Reputation: 15

Flask redirect from a child procces - make a waiting page using only python

today I try to make a "waiting page" using Flask. I mean a client makes a request, I want to show him a page like "wait the process can take a few minutes", and when the process ends on the server display the result.I want to display "wait" before my function manageBill.teste but redirect work only when it returned right?

@application.route('/teste', methods=['POST', 'GET'])
def test_conf():
if request.method == 'POST':
    if request.form.get('confList') != None:
        conf_file = request.form.get('confList')
        username = request.form.get('username')
        password = request.form.get('password')
        date = request.form.get('date')
        if date == '' or conf_file == '' or username == '' or password == '':
            return "You forget to provide information"
        newpid = os.fork()
        if newpid == 0: # in child procces
            print('A new child ',  os.getpid())
            error = manageBill.teste(conf_file, username, password, date)
            print ("Error :" + error)
            return redirect('/tmp/' + error)
        else: # in parent procces
            return redirect('/tmp/wait')
        return error
return manageBill.manageTest()`

My /tmp route:

@application.route('/tmp/<wait>')
def wait_teste(wait):
    return "The procces can take few minute, you will be redirected when the teste is done.<br>" + wait

Upvotes: 1

Views: 492

Answers (1)

Bailey Parker
Bailey Parker

Reputation: 15903

If you are using the WSGI server (the default), requests are handled by threads. This is likely incompatible with forking.

But even if it wasn't, you have another fundamental issue. A single request can only produce a single response. Once you return redirect('/tmp/wait') that request is done. Over. You can't send anything else.

To support such a feature you have a few choices:

  1. The most common approach is to have AJAX make the request to start a long running process. Then setup an /is_done flask endpoint that you can check (via AJAX) periodically (this is called polling). Once your endpoint returns that the work is done, you can update the page (either with JS or by redirecting to a new page).
  2. Have /is_done be a page instead of an API endpoint that is queried from JS. Set an HTTP refresh on it (with some short timeout like 10 seconds). Then your server can send a redirect for the /is_done endpoint to the results page once the task finishes.

Generally you should strive to serve web requests as quickly as possible. You shouldn't leave connections open (to wait for a long task to finish) and you should offload these long running tasks to a queue system running separately from the web process. In this way, you can scale your ability to handle web requests and background processes separately (and one failing does not bring the other down).

Upvotes: 1

Related Questions