简体   繁体   中英

How to async await flask endpoint from python function

I have a class that contains a function that I would like to be able to invoke by invoking a flask-resful endpoint. Is there a way to define an asynchronous function that would await/subscribe to this endpoint to be called? I can make changes to the flask app (but can't switch to SocketIO) as well if required or write some sort of async requests function. I can only work with the base Anaconda 3.7 library and I don't have any additional message brokers installed or available.

class DaemonProcess:
    def __init__(self):
        pass

    async def await_signal():
         signal = await http://ip123/signal
         self.(process_signal)  # do stuff with signal

For context, this isn't the main objective of the process. I simply want to be able to use this to tell my process remotely or via UI to shut down worker processes either gracefully or forcefully. The only other idea I came up with is pinging a database table repeatedly to see if a signal has been inserted, but time is of the essence and would require pinging at too short of intervals in my opinion and an asynchronous approach would be favored. The database would be SQLite3 and it doesn't appear to support update_hook callbacks.

Here's sample pattern to send a singal and process it:

import asyncio
import aiotools

class DaemonProcess
    async def process(reader, writer):
        data = await reader.read(100)
        writer.write(data)
        print(f"We got a message {data} - time to do something about it.")
        await writer.drain()
        writer.close()

    @aiotools.server
    async def worker(loop, pidx, args):
         server = await asyncio.start_server(echo, '127.0.0.1', 8888,
         reuse_port=True, loop=loop)
         print(f'[{pidx}] started')
         yield  # wait until terminated
         server.close()
         await server.wait_closed()
         print(f'[{pidx}] terminated')

     def start(self):
         aiotools.start_server(myworker, num_workers=4)


if __name__ == '__main__':
    # Run the above server using 4 worker processes.
    d = DaemonProcess()
    d.start()

if you save it in a file, for example, process.py , you should be able to start it:

python3 process.py

Now once you have this daemon in background, you should be able to ping it (see a sample client below):

import asyncio

async def tcp_echo_client(message):
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)

    print(f'Send: {message!r}')
    writer.write(message.encode())
    await writer.drain()

    data = await reader.read(100)
    print(f'Received: {data.decode()!r}')

    print('Close the connection')
    writer.close()
    await writer.wait_closed()

And now, somewhere in your Flask view, you should be able to invoke:

asyncio.run(tcp_echo_client('I want my daemon to do something for me'))

Notice this all used localhost 127.0.0.1 and port 8888 , so those to be made available unless you have your own ports and IPs, then you'll need to configure them accordingly.

Also notice the use of aiotools which is a module providing a set of common asyncio patterns (daemons, etc...).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM