2016-05-06 43 views
2

這是另一個flask dev服務器重新加載器問題。有一百萬個問題問爲什麼它將所有東西加載兩次,而這不是其中之一。我知道它將所有東西加載了兩次,我的問題涉及到處理這個現實,我還沒有找到一個答案,我想解決我想要做的。使用Flask dev服務器重新加載器處理多個應用程序對象的atexit

我的問題是,我如何清理出口處的所有應用程序對象?

我目前的做法如下所示。在這個例子中,我使用atexit函數運行我的清理代碼。

from flask import Flask 

app = Flask(__name__) 
print("start_app_id: ", '{}'.format(id(app))) 

import atexit 
@atexit.register 
def shutdown(): 
    print("AtExit_app_id: ", '{}'.format(id(app))) 
    #do some cleanup on the app object here 

if __name__ == "__main__": 
    import os 
    if os.environ.get('WERKZEUG_RUN_MAIN') == "true": 
     print("reloaded_main_app_id: ", '{}'.format(id(app))) 
    else: 
     print("first_main_app_id: ", '{}'.format(id(app))) 

    app.run(host='0.0.0.0', debug=True) 

此代碼的輸出如下所示:

start_app_id: 140521561348864 
first_main_app_id: 140521561348864 
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 
* Restarting with stat 
start_app_id: 140105598483312 
reloaded_main_app_id: 140105598483312 
* Debugger is active! 
* Debugger pin code: xxx-xxx-xxx 
^CAtExit_app_id: 140521561348864 

注意,第一加載時,將創建具有ID「864的應用程序對象。在自動重新加載期間,會創建一個ID爲'312的新應用程序對象。然後,當我按下Ctrl-C(最後一行)時,會調用atexit例程,原始的'864應用程序對象是可以使用應用程序變量訪問的對象 - 而不是更新的'312應用程序對象。

我希望能夠清理服務器關閉或Ctrl-C(在本例中爲'864和'312)時浮動的所有應用程序對象。任何建議如何做到這一點?或者,如果我可以在重新加載後創建的新的'312對象上運行清理,我也可以做這個工作 - 但是我目前的方法只能讓我清理原始的應用程序對象。

謝謝。

UPDATE1:我發現了一個link使用try /終於代替atexit對鉤來完成我上面列出來做到這一點建議。切換到這個結果完全相同的行爲的atexit,因此不會與我的問題有所幫助:

from flask import Flask 

app = Flask(__name__) 
print("start_app_id: ", '{}'.format(id(app))) 

if __name__ == "__main__": 
    import os 
    if os.environ.get('WERKZEUG_RUN_MAIN') == "true": 
     print("reloaded_main_app_id: ", '{}'.format(id(app))) 
    else: 
     print("first_main_app_id: ", '{}'.format(id(app))) 

    try: 
     app.run(host='0.0.0.0', debug=True) 
    finally: 
     print("Finally_app_id: ", '{}'.format(id(app))) 
     #do app cleanup code here 

回答

2

後有些是通過WERKZEUG挖源頭我找到了答案。答案是不可能做我想做的事 - 這是設計。

當使用flask dev服務器(werkzeug)時,由於werkzeug服務器捕獲鍵盤中斷異常並在其上「通過」,因此無法在終止時清除所有現有應用程序對象(例如ctrl-C)。

def run_with_reloader(main_func, extra_files=None, interval=1, 
         reloader_type='auto'): 
    """Run the given function in an independent python interpreter.""" 
    import signal 
    reloader = reloader_loops[reloader_type](extra_files, interval) 
    signal.signal(signal.SIGTERM, lambda *args: sys.exit(0)) 
    try: 
     if os.environ.get('WERKZEUG_RUN_MAIN') == 'true': 
      t = threading.Thread(target=main_func, args=()) 
      t.setDaemon(True) 
      t.start() 
      reloader.run() 
     else: 
      sys.exit(reloader.restart_with_reloader()) 
    except KeyboardInterrupt: 
     pass 

如果更換上面的:你可以在WERKZEUG的_reloader.py在run_with_reloader函數的最後一行看到這個「除了一個KeyboardInterrupt:」用「終於」,然後運行在第二個代碼片段原來的問題,你會發現兩個創建的應用程序對象都會根據需要進行清理。有趣的是,第一個代碼片段(使用@atexit)在做出這些更改後仍不能按需要工作。

因此總而言之,您可以在使用flask dev服務器時清除所有現有的應用程序對象,但是您需要修改werkzeug源來執行此操作。

相關問題