简体   繁体   English

如何在 flask API Python 中移出 app.run()

[英]How to move out of app.run() in flask API Python

I am working on python project which includes starting a flask API server on a button click.我正在研究 python 项目,其中包括单击按钮启动flask API server For buttons and UI I am using pyqt5 .对于按钮和 UI,我使用的是pyqt5 So on start server button click flask api server will start and on stop server button click, flask api server will stop. So on start server button click flask api server will start and on stop server button click, flask api server will stop.

I am able to start the server but the problem is when we start the flask api server, we use app.run(HOST, 80) .我能够启动服务器,但问题是当我们启动 flask api 服务器时,我们使用app.run(HOST, 80) During this the control always remains here and doesnt move out of it due to which when I click stop button, it doesnt stop.在此期间,控件始终保留在此处并且不会移出,因此当我单击停止按钮时,它不会停止。 Below is the code:下面是代码:

app.py应用程序.py

import sys
import time
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from server import start_local_server
from PyQt5.QtCore import pyqtSlot
from threading import Thread


run = True


def start_api_server():
    while run:
        start_local_server()
        print("server is running")
    time.sleep(1)
    print("SERVER HAS STOPPED")


class App(QWidget):
    global run

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 button - pythonspot.com'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 200
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        start_btn = QPushButton('Start Server', self)
        start_btn.move(100, 70)
        start_btn.clicked.connect(self.on_click_start_btn)

        stop_btn = QPushButton('Stop Server', self)
        stop_btn.move(200, 70)
        stop_btn.clicked.connect(self.on_click_stop_btn)

        fun_btn = QPushButton('Click to check responsiveness', self)
        fun_btn.move(150, 100)
        fun_btn.clicked.connect(self.on_click_fun_btn)

        self.show()

    @pyqtSlot()
    def on_click_start_btn(self):
        Thread(target=start_api_server).start()
        
    @pyqtSlot()
    def on_click_stop_btn(self):
        print("Stop server ")
        run = False
        
    @pyqtSlot()
    def on_click_fun_btn(self):
        print('If it is working, this means UI is responsive')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

In above code, I have button click function on_click_start_btn this starts a thread with target start_api_server .在上面的代码中,我有按钮单击 function on_click_start_btn这将启动一个目标start_api_server的线程。 This will further start the local flask server.这将进一步启动本地 flask 服务器。 When I want to stop the server, I will simply make run as False which will break the start_api_server function and the server will stop.当我想停止服务器时,我将简单地让run as False这将破坏start_api_server function 并且服务器将停止。 As per my understanding this should work fine.据我了解,这应该可以正常工作。

Below is the code for flask api:下面是 flask api 的代码:

server.py服务器.py

import os
import datetime
from flask import Flask, jsonify
from flask_cors import CORS


app = Flask(__name__)
CORS(app)
wsgi_app = app.wsgi_app


@app.route('/api/status')
def check_status():
    return jsonify({'status': 'ok', 'date': datetime.datetime.now().isoformat()}), 200


def start_local_server():
    HOST = os.environ.get('SERVER_HOST', 'localhost')
    try:
        PORT = int(os.environ.get('SERVER_PORT', '5555'))
    except ValueError:
        PORT = 5555
    app.run(HOST, 80)

The problem occurs in above flask code.问题出现在上面的 flask 代码中。 In above code, there is function start_local_server() which we are using in app.py .在上面的代码中,我们在 app.py 中使用了app.py start_local_server() In this we have app.run() , when our code reaches here, it always remains here and never moves out it due to which I am not able to stop this server.在这个我们有app.run() ,当我们的代码到达这里时,它总是留在这里并且永远不会移出它,因此我无法停止这个服务器。

I want to simply make code where I can start and stop the flask server using button click but due to app.run , its not working.我想简单地编写代码,我可以使用按钮单击启动和停止 flask 服务器,但由于app.run ,它不起作用。 Can anyone please help me with this issue.谁能帮我解决这个问题。 Is there any alternative to above problem.是否有任何替代上述问题。 Please help.请帮忙。 Thanks谢谢

Updated code as per answer:根据答案更新代码:

server = Process

def start_local_server():
    global server
    server = Process(target=app.run, args=('localhost', 80))
    # HOST = os.environ.get('SERVER_HOST', 'localhost')
    # try:
    #     PORT = int(os.environ.get('SERVER_PORT', '5555'))
    # except ValueError:
    #     PORT = 5555
    # app.run(HOST, 80)


def stop_local_server():
    global server
    server.terminate()

You can run app.run() in a seperate Process .您可以在单独的Process中运行app.run() Multiprocessing would be helpful in your case, since you're using pyQt.多处理对您的情况会有所帮助,因为您使用的是 pyQt。

from multiprocessing import Process

server = Process(target=app.run, args=(HOST, 80))
server.start() # to start the server
server.terminate() # to terminate the server

You can take a deeper look at multiprocessing library documentation here https://docs.python.org/2/library/multiprocessing.html您可以在此处更深入地查看multiprocessing库文档https://docs.python.org/2/library/multiprocessing.html

You forgot to strart the server:)你忘了启动服务器:)

server = None

def start_local_server():
    global server
    server = Process(target=app.run, args=('localhost', 80))
    server.start()
    # HOST = os.environ.get('SERVER_HOST', 'localhost')
    # try:
    #     PORT = int(os.environ.get('SERVER_PORT', '5555'))
    # except ValueError:
    #     PORT = 5555
    # app.run(HOST, 80)


def stop_local_server():
    global server
    server.terminate()

I have resolved the issue by starting the API server in separate thread so that Ui keeps on working.我已经通过在单独的线程中启动 API 服务器解决了这个问题,以便 Ui 继续工作。 Then I am shutting down the API server using shutdown api然后我使用 shutdown api 关闭 API 服务器

run = True


def start_api_server():
    while run:
        start_local_server()
        
    time.sleep(1)
    print("SERVER HAS STOPPED")

@pyqtSlot()
def on_click_start_btn(self):
    Thread(target=start_api_server).start()

Above is the code to start the server on button click.以上是单击按钮时启动服务器的代码。 Below is how I am shutting it down:以下是我关闭它的方法:

@pyqtSlot()
def on_click_stop_btn(self):
    global run
    print("STOPPING SERVER")
    run = False
    try:
        x = requests.get("http://localhost:80/api/shutdown")
        rdata = x.text
        rdata = json.loads(rdata)
        if rdata['status']:
            print("Server shutting down")
        print(rdata)

    except Exception as e:
        print(e)

Above code calls a shutdown API which terminate the flask api server.上面的代码调用了一个关闭 API 来终止 flask api 服务器。 Below is the code for it:下面是它的代码:

def shutdown_server():
    func = request.environ.get('werkzeug.server.shutdown')
    if func is None:
        raise RuntimeError('Not running with the Werkzeug Server')
    func()


@app.route('/api/shutdown')
def shutdown():
    shutdown_server()
    return 'Server shutting down...'

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

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