Using a background thread with asyncio/futures with flask

Frank Millman frank at chagford.com
Fri Mar 22 06:09:10 EDT 2024


On 2024-03-20 10:22 AM, Thomas Nyberg via Python-list wrote:
> 
> Hello,
> 
> I have a simple (and not working) example of what I'm trying to do. This 
> is a simplified version of what I'm trying to achieve (obviously the 
> background workers and finalizer functions will do more later):
> 
> `app.py`
> 
> ```
> import asyncio
> import threading
> import time
> from queue import Queue
> 
> from flask import Flask
> 
> in_queue = Queue()
> out_queue = Queue()
> 
> 
> def worker():
>      print("worker started running")
>      while True:
>          future = in_queue.get()
>          print(f"worker got future: {future}")
>          time.sleep(5)
>          print("worker sleeped")
>          out_queue.put(future)
> 
> 
> def finalizer():
>      print("finalizer started running")
>      while True:
>          future = out_queue.get()
>          print(f"finalizer got future: {future}")
>          future.set_result("completed")
>          print("finalizer set result")
> 
> 
> threading.Thread(target=worker, daemon=True).start()
> threading.Thread(target=finalizer, daemon=True).start()
> 
> app = Flask(__name__)
> 
> 
> @app.route("/")
> async def root():
>      future = asyncio.get_event_loop().create_future()
>      in_queue.put(future)
>      print(f"root put future: {future}")
>      result = await future
>      return result
> 
> 
> if __name__ == "__main__":
>      app.run()
> ```
> 
> If I start up that server, and execute `curl http://localhost:5000`, it 
> prints out the following in the server before hanging:
> 
> ```
> $ python3 app.py
> worker started running
> finalizer started running
>   * Serving Flask app 'app'
>   * Debug mode: off
> WARNING: This is a development server. Do not use it in a production 
> deployment. Use a production WSGI server instead.
>   * Running on http://127.0.0.1:5000
> Press CTRL+C to quit
> root put future: <Future pending>
> worker got future: <Future pending cb=[Task.task_wakeup()]>
> worker sleeped
> finalizer got future: <Future pending cb=[Task.task_wakeup()]>
> finalizer set result
> ```
> 
> Judging by what's printing out, the `final result = await future` 
> doesn't seem to be happy here.
> 
> Maybe someone sees something obvious I'm doing wrong here? I presume I'm 
> mixing threads and asyncio in a way I shouldn't be.
> 
> Here's some system information (just freshly installed with pip3 install 
> flask[async] in a virtual environment for python version 3.11.2):
> 
> ```
> $ uname -a
> Linux x1carbon 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 
> (2024-02-01) x86_64 GNU/Linux
> 
> $ python3 -V
> Python 3.11.2
> 
> $ pip3 freeze
> asgiref==3.7.2
> blinker==1.7.0
> click==8.1.7
> Flask==3.0.2
> itsdangerous==2.1.2
> Jinja2==3.1.3
> MarkupSafe==2.1.5
> Werkzeug==3.0.1
> ```
> 
> Thanks for any help!
> 
> Cheers,
> Thomas

Hi Thomas

I am no expert. However, I do have something similar in my app, and it 
works.

I do not use 'await future', I use 'asyncio.wait_for(future)'.

HTH

Frank Millman




More information about the Python-list mailing list