如何在不使用ctrl-c的情况下停止烧瓶应用

vic*_*vic 75 python flask flask-extensions

我想通过使用flask-script来实现一个可以停止烧瓶应用的命令.我已经搜索了一段时间的解决方案.因为框架不提供"app.stop()"API,所以我很好奇如何编写代码.我正在研究Ubuntu 12.10和Python 2.7.3.

Zor*_*ayr 88

如果您只是在桌面上运行服务器,则可以公开端点以终止服务器(在关闭简单服务器时阅读更多信息):

from flask import request
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('/shutdown', methods=['POST'])
def shutdown():
    shutdown_server()
    return 'Server shutting down...'
Run Code Online (Sandbox Code Playgroud)

这是另一种更加包含的方法:

from multiprocessing import Process

server = Process(target=app.run)
server.start()
# ...
server.terminate()
server.join()
Run Code Online (Sandbox Code Playgroud)

如果这有帮助,请告诉我.

  • 你知道是否有办法获得'werkzeug.server.shutdown'属性而不需要请求上下文? (12认同)
  • 顺便说一句,第一种方法现在已被弃用:https://github.com/pallets/werkzeug/pull/1873 (9认同)
  • 我不得不将路线方法更改为'GET'以使其工作. (4认同)
  • 为了完整性,这个答案缺少你在请求上下文之外调用的函数来执行关闭,这只不过是对服务器的HTTP请求(可以来自/来自localhost) (4认同)
  • 在 Windows 上将 Flask 作为“进程”运行对我来说不起作用(因为 Windows 无法“fork”而出现酸洗错误),您的示例是在 Linux/MacOS 上运行的吗? (3认同)

Rub*_*rop 23

我使用线程做的略有不同

from werkzeug.serving import make_server

class ServerThread(threading.Thread):

    def __init__(self, app):
        threading.Thread.__init__(self)
        self.srv = make_server('127.0.0.1', 5000, app)
        self.ctx = app.app_context()
        self.ctx.push()

    def run(self):
        log.info('starting server')
        self.srv.serve_forever()

    def shutdown(self):
        self.srv.shutdown()

def start_server():
    global server
    app = flask.Flask('myapp')
    ...
    server = ServerThread(app)
    server.start()
    log.info('server started')

def stop_server():
    global server
    server.shutdown()
Run Code Online (Sandbox Code Playgroud)

我使用它来为restful api做端到端测试,我可以使用python请求库发送请求.

  • 我没有设法让其他东西工作,但这个解决方案效果很好!万分感谢!对于其他人:它也适用于烧瓶宁静! (3认同)

小智 16

您不必按CTRL+ C,但您可以提供一个端点来为您完成此操作:

from flask import Flask, jsonify, request
import json, os, signal

@app.route('/stopServer', methods=['GET'])
def stopServer():
    os.kill(os.getpid(), signal.SIGINT)
    return jsonify({ "success": True, "message": "Server is shutting down..." })
Run Code Online (Sandbox Code Playgroud)

现在您可以调用此端点来正常关闭服务器:

curl localhost:5000/stopServer
Run Code Online (Sandbox Code Playgroud)


Nam*_* VU 12

我的方法可以通过bash终端/控制台进行

1)运行并获取进程号

$ ps aux | grep yourAppKeywords
Run Code Online (Sandbox Code Playgroud)

2a)杀死进程

$ kill processNum
Run Code Online (Sandbox Code Playgroud)

2b)如果上面没有工作就杀了这个过程

$ kill -9 processNum
Run Code Online (Sandbox Code Playgroud)

  • 我几乎可以确定问题不是“如何终止进程”,问题是执行ctrl + c不会终止该进程。顺便说一句,我确实使用`kill -9 \`lsof -i:5000 -t \``因为只有1个应用程序可以使用该端口并且很容易。 (3认同)

dan*_*nvk 9

正如其他人指出的那样,您只能使用werkzeug.server.shutdown请求处理程序.我发现在另一个时间关闭服务器的唯一方法是向自己发送请求.例如,/kill此代码段中的处理程序将终止开发服务器,除非在下一秒期间有另一个请求进入:

import requests
from threading import Timer
from flask import request
import time

LAST_REQUEST_MS = 0
@app.before_request
def update_last_request_ms():
    global LAST_REQUEST_MS
    LAST_REQUEST_MS = time.time() * 1000


@app.route('/seriouslykill', methods=['POST'])
def seriouslykill():
    func = request.environ.get('werkzeug.server.shutdown')
    if func is None:
        raise RuntimeError('Not running with the Werkzeug Server')
    func()
    return "Shutting down..."


@app.route('/kill', methods=['POST'])
def kill():
    last_ms = LAST_REQUEST_MS
    def shutdown():
        if LAST_REQUEST_MS <= last_ms:  # subsequent requests abort shutdown
            requests.post('http://localhost:5000/seriouslykill')
        else:
            pass

    Timer(1.0, shutdown).start()  # wait 1 second
    return "Shutting down..."
Run Code Online (Sandbox Code Playgroud)

  • 这有效,但感觉...... _非常_ hacky。我知道已经有一段时间了,但是你有没有找到一种干净的方法来做到这一点,而不向自己发送请求? (3认同)

小智 7

如果您不在请求-响应处理范围内,您仍然可以:

import os
import signal

sig = getattr(signal, "SIGKILL", signal.SIGTERM)
os.kill(os.getpid(), sig)
Run Code Online (Sandbox Code Playgroud)


Bar*_*rli 7

request.environ.get 已弃用帕维尔·米纳耶夫的解决方案非常明确:

import os
from flask import Flask


app = Flask(__name__)
exiting = False

@app.route("/exit")
def exit_app():
    global exiting
    exiting = True
    return "Done"

@app.teardown_request
def teardown(exception):
    if exiting:
        os._exit(0)
Run Code Online (Sandbox Code Playgroud)


小智 6

这是一个古老的问题,但是谷歌搜索并没有给我提供有关如何完成此操作的任何见解。

因为我在这里没有正确阅读代码!(Doh!)它的作用是在……中RuntimeError不存在时引发一个。werkzeug.server.shutdownrequest.environ

因此,如果没有,我们可以做的request就是提高RuntimeError

def shutdown():
    raise RuntimeError("Server going down")
Run Code Online (Sandbox Code Playgroud)

并在app.run()返回时捕捉到:

...
try:
    app.run(host="0.0.0.0")
except RuntimeError, msg:
    if str(msg) == "Server going down":
        pass # or whatever you want to do when the server goes down
    else:
        # appropriate handling/logging of other runtime errors
# and so on
...
Run Code Online (Sandbox Code Playgroud)

无需向自己发送请求。


R J*_*R J 6

这是一个有点旧的线程,但是如果有人从后台运行的脚本开始尝试,学习或测试基本的flask应用,则停止它的最快方法是终止正在运行应用的端口上运行的进程上。注意:我知道作者正在寻找一种不杀死或停止该应用程序的方式。但这可能会对正在学习的人有所帮助。

sudo netstat -tulnp | grep :5001
Run Code Online (Sandbox Code Playgroud)

你会得到这样的东西。

tcp 0 0 0.0.0.0:5001 0.0.0.0:* LISTEN 28834 / python

要停止应用,请终止进程

sudo kill 28834
Run Code Online (Sandbox Code Playgroud)

  • 在进程被杀死之前,我必须使用“sudo Kill -9 28834”。 (2认同)

kip*_*ip2 5

如果您正在使用 CLI 并且只运行一个 Flask 应用程序/进程(或者更确切地说,您只想终止系统上运行的任何Flask 进程),您可以使用以下命令终止它:

kill $(pgrep -f flask)