【问题标题】:How to call a function when Apache terminates a Flask process?Apache 终止 Flask 进程时如何调用函数?
【发布时间】:2015-06-27 16:59:13
【问题描述】:

我有一个在 Apache HTTPD 后面运行的 Flask 应用程序。 Apache 被配置为有多个子进程。

Flask 应用程序在服务器上创建一个文件,该文件的名称与其进程 ID 相同。 代码如下所示:

import os

@app.before_first_request
def before_first_request():
    filename = os.getpid()
    with open(filename, 'w') as file:
        file.write('Hello')

当子进程被杀死/结束/终止时,我希望 Flask 应用程序删除此文件。

删除文件并不是很重要,因为这些文件不会占用太多空间,所以如果出现奇怪的错误,我不需要处理它们。但是对于正常的工作流程,我想在 Apache 关闭 Flask 进程时进行一些清理。

你知道最好的方法吗?

【问题讨论】:

    标签: python apache flask termination


    【解决方案1】:

    在优雅终止服务器控制的 Python 进程(例如在 Apache WSGI 上下文中运行的 Flask 应用程序,或者更好的是,在 Apache 后面的 Gunicorn 中运行的 Flask 应用程序)之前添加清理功能的最佳方法是使用 atexit 退出处理程序。

    详细说明您的原始示例,这里添加了用于清理 .pid 文件的退出处理程序:

    import atexit
    import os
    
    filename = '{}.pid'.format(os.getpid())
    
    @app.before_first_request
    def before_first_request():
        with open(filename, 'w') as file:
            file.write('Hello')
    
    def cleanup():
        try:
            os.remove(filename)
        except Exception:
            pass
    
    atexit.register(cleanup)
    

    【讨论】:

    • Apache/mod_wsgi 当然总是试图确保调用 atexit 回调,即使在由于请求超时等条件而必须关闭进程的情况下。在 gunicorn 中没有那么好一个保证,你必须更加小心在 gunicorn 下使用 atexit ,因为在各种情况下它不会被调用。在任何一种情况下,您都不应该依赖它,并且应用程序应该对后续运行中存在的文件(如果它不应该存在)具有弹性。如其他答案所述,要删除可能需要的单独任务。
    • 对于其他一些 WSGI 服务器,atexit 回调甚至可能根本不会被调用。我相信 uWSGI 仍然是这种情况,除非你强制它使用单个解释器,因为它没有采取措施确保在子解释器中调用 atexit 回调。它必须采取特殊步骤,因为 Python 不会在子解释器中调用 atexit 回调,而 Apache/mod_wsgi 正在使用特殊技巧来确保它们是。
    • 好消息@GrahamDumpleton!感谢您,以及os.remove 呼叫周围的异常保护。
    【解决方案2】:

    最简单的方法是在 Apache 进程之外处理这个问题。无法保证该进程始终会删除文件(例如,如果您在请求过程中重新启动 apache 服务器)。

    我过去采用的方法是使用cron。在存储库的某处编写一个小脚本,并按计划执行(通常每天都有效)。此脚本可以清除目录中所有超过 24 小时的文件,因此您将始终拥有 1 天的文件滚动窗口。

    这有两个好处:

    1. 您可以完全控制脚本,并且可以使用任何您想要的语言。
    2. 您可以用这些文件做一些花哨的事情。您可以压缩它们并将它们存储在别处、删除它们或对它们执行分析。完全由您决定!

    大多数脚本语言都有一个小的包装类,可以用来使cron 更友好。一个流行的 Ruby 是whenever

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多