简体   繁体   English

如何从python函数异步等待烧瓶端点

[英]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.我有一个包含一个函数的类,我希望能够通过调用一个flask-resful 端点来调用该函数。 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.如果需要,我也可以对 Flask 应用程序进行更改(但不能切换到 SocketIO)或编写某种异步请求函数。 I can only work with the base Anaconda 3.7 library and I don't have any additional message brokers installed or available.我只能使用基本的 Anaconda 3.7 库,而且我没有安装或可用的任何其他消息代理。

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.我只是希望能够使用它来远程或通过 UI 告诉我的进程以正常或强制关闭工作进程。 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.我想出的唯一其他想法是重复 ping 数据库表以查看是否已插入信号,但时间至关重要,在我看来需要以太短的间隔进行 ping,异步方法将受到青睐。 The database would be SQLite3 and it doesn't appear to support update_hook callbacks.数据库将是 SQLite3,它似乎不支持 update_hook 回调。

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:如果您将它保存在一个文件中,例如process.py ,您应该能够启动它:

python3 process.py

Now once you have this daemon in background, you should be able to ping it (see a sample client below):现在一旦你在后台运行了这个守护进程,你应该能够 ping 它(参见下面的示例客户端):

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:现在,在 Flask 视图中的某个地方,您应该能够调用:

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.请注意,所有这些都使用了 localhost 127.0.0.1和端口8888 ,因此除非您拥有自己的端口和 IP,否则它们将可用,然后您需要相应地配置它们。

Also notice the use of aiotools which is a module providing a set of common asyncio patterns (daemons, etc...).还要注意aiotools的使用,它是一个提供一组通用异步模式(守护进程等)的模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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