dper
dper

Reputation: 904

Python, run a background task while not blocking the api thread, using Quart

I am trying to create a python api that works on the input data and run different scripts according to the provided input. I was using flask + gunicorn earlier with 8 workers. I got to know about asyncio library and I switched from flask to quart and gunicorn to hypercorn using the following [guide][1].

My functions look like :

@app.route("/pyscript", methods=["POST"])
#@cross_origin(supports_credentials=True)
async def pyscript():
    #check for pre defined token
    try:
        if(token == consts.authToken):
            print("TOKEN VALIDATED")
        else:
            return jsonify({'message': 'token is invalid'})
    except:
        return jsonify({'message': 'token is invalid'})
    json_all_data = await request.get_json(force=True)
    print(json_all_data)
    json_data = json_all_data['data']
    json_data = json.dumps(json_data)
    if json_data is None:
        return "Bad request, invalid JSON Format inserted", 401
    json_LOC = (json_all_data['LOC'])
    json_LOI = (json_all_data['LOB'])
    try:
        if(json_LOC in keys and json_LOI in keys[json_LOC]):
            chosen_operation_function = carriers.get(json_LOC).get(json_LOI)
            return_UUID = uuid.uuid4()
            app.add_background_task(run_task(json_data, json_LOC, json_LOI, chosen_operation_function, return_UUID))
            out_int = {
                "job_id" : return_UUID,
                "status" : "Running",
                "input" : json.loads(json_data)
                 }
            return out_int, 202    
        else:
            return jsonify({'message': 'LOC/LOB is invalid'})
    except Exception as e:
        print(e)
        return e   

run_task is a function in other file that is an async defined function.

Expected Output : I wanted to process the run_task in background while returning 202 response and a json data associated with it.

Whats happening : The value is returned in the postman request but the server shows the following error :

Traceback (most recent call last):
  File "/home/user/.local/lib/python3.8/site-packages/quart/app.py", line 1396, in _wrapper
    await copy_current_app_context(func)(*args, **kwargs)
  File "/home/user/.local/lib/python3.8/site-packages/quart/ctx.py", line 333, in wrapper
    return await app_context.app.ensure_async(func)(*args, **kwargs)
  File "/home/user/.local/lib/python3.8/site-packages/quart/utils.py", line 55, in _wrapper
    None, copy_context().run, partial(func, *args, **kwargs)
TypeError: the first argument must be callable

I am not able to identify the error and any help would be appreciated.

Thanks [1]: https://pgjones.gitlab.io/quart/how_to_guides/flask_migration.html

Upvotes: 0

Views: 1416

Answers (1)

pgjones
pgjones

Reputation: 7029

I think you are calling add_background_task incorrectly, rather than,

app.add_background_task(run_task(json_data, json_LOC, json_LOI, chosen_operation_function, return_UUID))

It should be called as,

app.add_background_task(run_task, json_data, json_LOC, json_LOI, chosen_operation_function, return_UUID)

Note that run_task is not called in the second example in your code, instead it and the arguments to call it are passed to the add_background_task function.

Upvotes: 2

Related Questions