2013-03-22 17 views
35

Tôi muốn thực hiện lệnh có thể dừng ứng dụng bình bằng cách sử dụng bộ mã dạng bình. Tôi đã tìm kiếm giải pháp một lúc. Vì khung công tác không cung cấp API "app.stop()", tôi tò mò về cách viết mã này. Tôi đang làm việc trên Ubuntu 12.10 và Python 2.7.3.Cách dừng ứng dụng bình mà không sử dụng ctrl-c

+0

Tại sao bạn cần có thể dừng ứng dụng của mình khỏi tập lệnh? (Công cụ tốt nhất cho công việc sẽ phụ thuộc vào những gì bạn đang cố gắng làm). –

+0

Nghiêm túc, bạn đang cố gắng làm gì ở đây? Nếu bạn đang nói về devserver cho phát triển, nó là hoàn toàn tốt đẹp để ngăn chặn nó như thế. Trong quá trình sản xuất, bạn không triển khai như thế này và bạn có thể dừng yêu cầu bất cứ lúc nào bạn muốn, vì vậy ứng dụng "ngừng chạy". –

+0

@SeanVieira Tôi muốn biết nếu có bất kỳ giải pháp để làm điều này. – vrootic

Trả lời

44

Nếu bạn chỉ chạy các máy chủ trên máy tính của bạn, bạn có thể tiếp xúc với một thiết bị đầu cuối để giết các máy chủ (đọc thêm tại 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...' 

Đây là cách tiếp cận khác được chứa hơn:

from multiprocessing import Process 

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

Hãy cho tôi biết nếu điều này có ích.

+8

Bạn có biết có cách nào để lấy thuộc tính 'werkzeug.server.shutdown' mà không cần bối cảnh yêu cầu không? – akatkinson

+1

Tôi đã phải thay đổi phương thức định tuyến thành 'GET' để làm cho nó hoạt động. –

+2

Để hoàn thành câu trả lời này thiếu chức năng bạn sẽ gọi bên ngoài ngữ cảnh yêu cầu để tắt máy, điều này sẽ không có gì hơn yêu cầu HTTP tới máy chủ (có thể bắt nguồn từ/đến localhost) – JamesHutchison

4

Khi những người khác đã chỉ ra, bạn chỉ có thể sử dụng werkzeug.server.shutdown từ trình xử lý yêu cầu. Cách duy nhất tôi đã tìm thấy để tắt máy chủ tại một thời điểm khác là gửi một yêu cầu cho chính mình. Ví dụ, /kill xử lý trong đoạn mã này sẽ giết chết các máy chủ dev trừ khi yêu cầu khác đi kèm trong trong lần thứ hai tiếp theo:

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

. _very_ hacky. Tôi biết nó đã được một thời gian, nhưng bạn đã bao giờ tìm thấy một cách sạch sẽ làm điều này, mà không cần gửi một yêu cầu cho chính mình? – Juicy

2

Phương pháp của tôi có thể được tiến hành thông qua thiết bị đầu cuối bash/console

1) chạy và nhận số quá trình

$ ps aux | grep yourAppKeywords 

2a) giết chết quá trình

$ kill processNum 

2b) giết chết quá trình nếu ở trên không làm việc

$ kill -9 processNum 
+0

Tôi gần như chắc chắn rằng câu hỏi không phải là "làm thế nào để giết một quá trình", và vấn đề là làm ctrl + c không giết nó. Btw, tôi sử dụng 'kill -9 \' lsof -i: 5000 -t \ '' cuz không chỉ khác 1 ứng dụng có thể sử dụng cổng và dễ dàng. – erm3nda

2

Đây là một câu hỏi cũ, nhưng googling đã không cho tôi bất kỳ cái nhìn sâu sắc về cách thức thực hiện điều này.

Vì tôi không đọc chính xác code here! (Doh!) gì nó làm là để nâng cao một RuntimeError khi không có werkzeug.server.shutdown trong request.environ ...

Vì vậy, những gì chúng ta có thể làm gì khi không có request là nâng cao một RuntimeError

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

và nắm bắt điều đó khi số app.run() trả về:

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

Không cần gửi cho bạn yêu cầu.

7

tôi đã làm nó hơi khác nhau sử dụng đề

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

tôi sử dụng nó để làm đầu đến cuối bài kiểm tra cho api yên tĩnh, nơi tôi có thể gửi các yêu cầu sử dụng thư viện yêu cầu python.

+0

Tôi không quản lý để có được những thứ khác để làm việc nhưng giải pháp này hoạt động tuyệt vời! Cảm ơn một tấn! Đối với những người khác: nó cũng làm việc với bình yên tĩnh! –

+0

Điều này dường như chặn trên cửa sổ cho đến khi tôi nhấn nó với một yêu cầu khác ... bất kỳ cách nào xung quanh điều đó? – Claudiu

+0

Tôi gặp vấn đề tương tự với @Claudiu, ngoại trừ Linux với python 3.6.2 – micahscopes

Các vấn đề liên quan