flask + asyncio app works on windows, but not on linux? ("Future <Future pending> attached to a different loop" error)

Viewed 99

I have a python script which creates a flask app, whose routes use asyncio (to communicate over bluetooth, using bleak). The script works fine on windows, but when run from a raspberry pi (with same python, flask & asyncio versions), calling an asynchronous function through the flask app gives the error:

"RuntimeError: Task [...] got Future <Future pending> attached to a different loop"

I'm new to both flask and asyncio, but I gather that this means the flask route is calling the function in a new thread, and I need to somehow add a task to the already running thread instead. But is there a reason the behavior is different on different operating systems?

If I interrupt the script with ctrl-C, the function that caused the error seems to be completed successfully.

Python 3.9, Flask 2.0.2 with async

The script:

from flask import Flask, render_template, request, redirect
import asyncio
from bleak import BleakClient, BleakScanner

IO_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"

COMMANDS = {
    "power" : bytes.fromhex("1F30 4145 09")
}

async def discover():
    while True:
        devices = await BleakScanner.discover()
        for d in devices:
            if d.name:
                print(d.name)
                if "GxTimer_" in d.name:
                    print("Timer Found")
                    return d.address

async def main():
    address = await discover()
    while True:
        try:
            async with BleakClient(address) as client:
                await client.pair()

                app = Flask(__name__)

                @app.route('/')
                def index():
                    return render_template('index.html')

                @app.route('/power', methods=['POST'])
                async def power():
                    await client.write_gatt_char(IO_UUID, COMMANDS['power'])
                    return redirect('/')

                if __name__ == '__main__':
                    app.run(debug=False, host='0.0.0.0')

        except Exception as e:
            print(e)


asyncio.run(main())
0 Answers
Related