Python Forum
Starlette: accumulated tasks. Why?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Starlette: accumulated tasks. Why?
#1
Hi everyone!
I have test project:

    from starlette.applications import Starlette
    from starlette.responses import JSONResponse
    from starlette.routing import Route
    
    from starlette.requests import Request
    from starlette.background import BackgroundTasks, BackgroundTask
    
    
    def parse_json(json_data):
        print(json_data['value'])
    
    
    async def testbground(request: Request):
        try:
            json_data = await request.json()
        except JSONDecodeError:
            print('cannot_parse_request_body')
            raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail='cannot_parse_request_body')
        except:
            return JSONResponse({"status": "Error"}, status_code=500)
    
        if 'value' in json_data.keys():
            tasks.add_task(parse_json, json_data)
        else:
            raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail='wrong_json_format')
    
        return JSONResponse({"status": "OK"}, background=tasks, status_code=200)
    
    
    
    
    tasks = BackgroundTasks()
    
    app = Starlette(debug=True, routes=[
        Route('/testbground', endpoint=testbground, methods=['POST']),
    ])
And have sender.py for tests:

    import requests
    
    url = 'http://localhost:8000/testbground'
    
    for i in range(10):
        data = {'value': i}
    
        try:
            r = requests.post(url, json=data, timeout=5)
        except Exception as e:
            print(e)
Result:

Output:
0 0 1 0 1 2 0 1 2 3 ... 0 1 2 3 4 5 6 7 8 9

But I was expecting another result.

Output:
0 1 2 ... 9
What is wrong? How can i add tasks to pull right?
Reply
#2
The BackgroundTasks are not deleted when the tasks has been finished, so it's executing all time all existing tasks.

Remove line 32: tasks = BackgroundTasks()

In line 23 replace:
task = BackgroundTask(parse_json, json_data)
# don't forget to import BackgroundTask
# don't use BackgroundTasks

And change
    return JSONResponse({"status": "OK"}, background=tasks, status_code=200)
to
    return JSONResponse({"status": "OK"}, background=task, status_code=200)
Output:
INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: 127.0.0.1:61469 - "POST /testbground HTTP/1.1" 200 OK 5 INFO: 127.0.0.1:61471 - "POST /testbground HTTP/1.1" 200 OK 6 INFO: 127.0.0.1:61474 - "POST /testbground HTTP/1.1" 200 OK 0 INFO: 127.0.0.1:61476 - "POST /testbground HTTP/1.1" 200 OK 1 INFO: 127.0.0.1:61478 - "POST /testbground HTTP/1.1" 200 OK 2 INFO: 127.0.0.1:61480 - "POST /testbground HTTP/1.1" 200 OK 3 INFO: 127.0.0.1:61482 - "POST /testbground HTTP/1.1" 200 OK 4
The implementation of these classes are simple: https://github.com/encode/starlette/blob...ound.py#L7
The Response class takes the background and run it as a coroutine or as a thread if it's not a coroutine.

Why the error happens, is also self-explanatory. In BackgroundTasks class is no automagically method to remove a task.
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
(Jul-06-2021, 01:56 PM)DeaD_EyE Wrote: The BackgroundTasks are not deleted when the tasks has been finished, so it's executing all time all existing tasks.
Oh! This explains everything. Thanks so much!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to manage a dynamic list of tasks with asyncio tperrot 0 426 Aug-06-2021, 09:07 AM
Last Post: tperrot

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020