在没有 CMD 的情况下运行 Flask API

时间:2021-07-27 07:04:49

标签: python flask tkinter

我在一家在本地计算机和服务器上部署系统的公司工作。

给我的任务是创建一个 python 应用程序,它与 plc 通信并使用 Reactjs/Electron.js 显示收集的数据或将数据保存在 MS SQL Server 上。

我的想法是使用 tkinter 创建 gui 并通过创建 <filename>.spec 文件和 pyinstaller 将其转换为应用程序,看起来像 XAMPP,我可以在其中重新启动和启动api。

如果我使用 tkinter 我应该从哪里开始?当 gui 打开时,我设法启动了后端,但我不知道停止或重新启动后端。我对 threads 也没有太多想法,但我认为它会帮助我创造我想要的东西。

我也在寻找是否可以使用 XAMPP 作为主机来运行 api 但没有运气。

如果你们有更好的方法在没有 cmd 的情况下在本地主机上运行 api 真的会有所帮助

1 个答案:

答案 0 :(得分:0)

好的,所以这花了一段时间,但我想出了如何不使用 subprocess(主要是因为还有另一个关于不使用 python 的问题,所以唯一的方法是将烧瓶应用程序转换为 { {1}} 然后使用 .exe 但我发现如何只使用 python 来做到这一点),主要问题(简单的修复,但在使用 subprocess 时也必须解决)是烧瓶重新启动服务器启动另一个进程,因此您必须在 subprocess.Popen 方法中使用 use_reloader=False。评论中的解释:

app.py

.run()

run.py

# import what's necessary
from flask import Flask, render_template_string, url_for
from flask import request


app = Flask(__name__)


# sample route
@app.route('/')
def home():
    return render_template_string('<a href="{{ url_for("about") }}">To About Page</a>'
                                  '<h1>Home Page</h1>')


# sample route
@app.route('/about')
def about():
    return render_template_string('<a href="{{ url_for("home") }}">To Home Page</a>'
                                  '<h1>About Page</h1>')


# important route that will do the stopping part since that was a requirement in the question
# link to this in the answer at the bottom
@app.route('/kill_server', methods=['GET'])
def kill_server():
    func = request.environ.get('werkzeug.server.shutdown')
    if func is None:
        raise RuntimeError('Not running with the Werkzeug Server. Could not shut down server.')
    func()
    return 'Server shutting down...'


# to prevent this from running when importing
if __name__ == '__main__':
    app.run(debug=True)

来源:

唯一的问题是在控制台中显示启动消息,有一种方法可以通过将 # import all that is necessary from tkinter import Tk, Text, Button, Frame from for_so_dir.app import app as server from threading import Thread from queue import Queue, Empty import requests import logging.handlers # simple dictionary to avoid using `global`, just a preference of mine info = {'server_is_running': False} # the function that starts server (multiprocessing is not possible with flask as far as I know) # basically checks if the server is not running already and if it is not then starts a thread # with the server (which is the same as `app` in the app.py) and sets that server is running def start_server(): if info['server_is_running']: return Thread(target=server.run, kwargs={'debug': True, 'use_reloader': False}, daemon=True).start() info['server_is_running'] = True # function from stopping server, again in the answer at the bottom, but basically # this sends a request to the server and that request executes a function # that stops the server def stop_server(): if not info['server_is_running']: return requests.get('http://127.0.0.1:5000/kill_server') # function for showing the logs in the Text widget, it simply tries to get data from # the queue (if there is nothing it simply loops again) and then inserts that data into # the text widget def update_text_log(): try: data = queue.get(block=False) except Empty: pass else: log.config(state='normal') log.insert('end', data.msg + '\n') log.config(state='disabled') finally: root.after(100, update_text_log) # this `if statement` is not that necessary in the current code but it might as well # stay here if __name__ == '__main__': # initialise the Queue queue = Queue() # now the main part, to get the info from flask you need to use `logging` # since that is what it uses for all the messages, and use the `QueueHandler` # to put the messages in the queue and then update them using the above # function logging.basicConfig(handlers=(logging.handlers.QueueHandler(queue), )) # simple `tkinter` stuff root = Tk() # this part can be removed or made toggleable but it allows to easier see how # this works in action root.attributes('-topmost', True) log = Text(root, state='disabled') log.pack(expand=True, fill='both') update_text_log() button_frame = Frame(root) button_frame.pack(fill='x') Button(button_frame, text='Start Server', command=start_server).pack(expand=True, fill='x', side='left') Button(button_frame, text='Stop Server', command=stop_server).pack(expand=True, fill='x', side='right') root.mainloop() 然后 import os 添加到 os.environ['WERKZEUG_RUN_MAIN'] = 'true' 文件来删除它,但有一个小问题然后使用按钮停止服务器将执行以下操作:app.py(至少在 Windows 上)因此您必须找到一种方法来解决此问题,因为我还不能这样做