2013-03-22 10 views
35

Voglio realizzare un comando che può fermare applicazione pallone utilizzando pallone-script. Ho cercato la soluzione per un po '. Poiché il framework non fornisce l'API "app.stop()", sono curioso di sapere come codificarlo. Sto lavorando su Ubuntu 12.10 e Python 2.7.3.come smettere di applicazione pallone senza usare ctrl-c

+0

Perché è necessario essere in grado di interrompere l'applicazione da uno script? (Lo strumento migliore per il lavoro dipenderà da ciò che stai cercando di fare). –

+0

Seriamente, cosa stai cercando di fare qui? Se stai parlando di devserver per lo sviluppo, è perfettamente corretto fermarlo in questo modo. In produzione non si distribuisce in questo modo e si può interrompere una richiesta in qualsiasi momento, quindi "l'app smette di funzionare". –

+0

@SeanVieira Voglio sapere se ci sono soluzioni per fare questo. – vrootic

risposta

44

Se sono solo in esecuzione il server sul desktop, è possibile esporre un endpoint per uccidere il server (continua a Shutdown The Simple Server):

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...' 

Ecco un altro approccio che è più contenuto:

from multiprocessing import Process 

server = Process(target=app.run) 
server.start() 
# ... 
server.terminate() 
server.join() 

fatemi sapere se questo aiuta.

+8

Sai se esiste un modo per ottenere la proprietà 'werkzeug.server.shutdown' senza bisogno di un contesto di richiesta? – akatkinson

+1

Ho dovuto cambiare il metodo del percorso in "GET" per farlo funzionare. –

+2

Per completezza questa risposta manca la funzione che si chiamerebbe al di fuori di un contesto di richiesta per eseguire l'arresto, che non sarebbe nient'altro che una richiesta HTTP al server (che può provenire da/a localhost) – JamesHutchison

4

Come altri hanno sottolineato, è possibile utilizzare solo werkzeug.server.shutdown da un gestore richieste. L'unico modo in cui ho trovato di spegnere il server in un altro momento è quello di inviare una richiesta a te stesso. Ad esempio, il gestore /kill in questo frammento ucciderà il server dev meno che un altro richiesta arriva durante il prossimo secondo:

import requests 
from threading import Timer 
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..." 
+0

funziona ma si sente .. ._very_ hacky. So che è passato un po 'di tempo, ma hai mai trovato un modo pulito per farlo, senza inviare una richiesta a te stesso? – Juicy

2

Il mio metodo può procedere tramite il morsetto bash/console

1) gestito e ottenere il numero di processo

$ ps aux | grep yourAppKeywords 

2a) uccidere il processo

$ kill processNum 

2b) uccidere il processo se sopra non funziona

$ kill -9 processNum 
+0

Sono quasi sicuro che la domanda non è "come uccidere un processo", e il problema è che fare ctrl + c non lo uccide. A proposito, io uso 'kill -9 \' lsof -i: 5000 -t \ '' cuz nientemeno che solo 1 app può usare la porta ed è facile. – erm3nda

2

Questa è una vecchia questione, ma googling non mi ha dato una visione chiara su come raggiungere questo obiettivo.

Perché non ho letto correttamente il code here! (Doh!) Ciò che fa è quello di sollevare un RuntimeError quando non c'è werkzeug.server.shutdown nel request.environ ...

Allora cosa possiamo fare quando non c'è request è quello di sollevare una RuntimeError

def shutdown(): 
    raise RuntimeError("Server going down") 

e cattura che quando app.run() rendimenti:

... 
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 
... 

Non c'è bisogno di inviare a te stesso una richiesta.

7

ho fatto un po 'diversi thread utilizzando

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() 

Io lo uso per fare un capo all'altro test per RESTful API, dove posso inviare richieste utilizzando la libreria richieste pitone.

+0

Non sono riuscito a far funzionare le altre cose ma questa soluzione funziona benissimo! Grazie mille! Per le altre persone: funziona anche con il pallone riposante! –

+0

Questo sembra bloccare su Windows fino a quando non lo colpisco con un'altra richiesta ... in ogni modo intorno a questo? – Claudiu

+0

Sto avendo lo stesso problema di @Claudiu, tranne su Linux con Python 3.6.2 – micahscopes