2016-05-06 44 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源来执行此操作。

相关问题