【问题标题】:How do I run a long-running job in the background in Python如何在 Python 后台运行长时间运行的作业
【发布时间】:2016-03-23 04:15:36
【问题描述】:

我有一个运行长时间作业(大约几个小时)的网络服务。我正在使用 Flask、Gunicorn 和 nginx 开发它。

我正在考虑做的是让需要很长时间才能完成的路线,调用一个创建线程的函数。然后该函数将返回一个 guid 返回到路由,并且该路由将返回一个 url(使用该 guid),用户可以使用该 url 检查进度。我正在使线程成为守护进程(thread.daemon = True),以便在我的调用代码退出(意外)时线程退出。

这是正确的使用方法吗?它有效,但这并不意味着它是正确的。

my_thread = threading.Thread(target=self._run_audit, args=())
my_thread.daemon = True
my_thread.start()

【问题讨论】:

    标签: python multithreading nginx flask


    【解决方案1】:

    Celery 和 RQ 对简单任务进行了过度设计。 看看这个文档 - https://docs.python.org/3/library/concurrent.futures.html

    同时查看示例,如何在后台为 Flask 应用运行长时间运行的作业 - https://stackoverflow.com/a/39008301/5569578

    【讨论】:

    • future 的好处,它是 grpc(以及其他)用来处理并行请求的方法
    • 但是线程不会在 python 中锁定应用程序?
    【解决方案2】:

    处理此类问题的更常规方法是从基本应用程序中提取操作并在外部调用它,使用像 Celery 这样的任务管理器系统。

    使用this 教程,您可以创建您的任务并从您的网络应用程序中触发它。

    from flask import Flask
    
    app = Flask(__name__)
    app.config.update(
        CELERY_BROKER_URL='redis://localhost:6379',
        CELERY_RESULT_BACKEND='redis://localhost:6379'
    )
    celery = make_celery(app)
    
    
    @celery.task()
    def add_together(a, b):
        return a + b
    

    然后就可以运行了:

    >>> result = add_together.delay(23, 42)
    >>> result.wait()
    65
    

    记住你需要单独运行worker:

    celery -A your_application worker
    

    【讨论】:

    • 我认为@ali-nikneshan 引用的教程是:flask.pocoo.org/docs/0.12/patterns/celery
    • 像我这样的多平台用户的旁注:Celery 4.x 不再支持 Windows。
    • @maugch 哦,你仍然可以使用-P solo
    【解决方案3】:

    好吧,虽然你的方法没有错,但基本上它可能会导致你的程序用尽可用线程。正如Ali 提到的,一般的方法是使用像RQCelery 这样的作业队列。但是,您无需提取函数即可使用这些库。对于 Flask,我建议您使用 Flask-RQ。上手很简单:

    RQ

    pip install flask-rq
    

    请记住在您的 Flask 应用中使用之前安装 Redis。

    只需在 Flask 函数中使用 @Job Decorator:

    from flask.ext.rq import job
    
    
    @job
    def process(i):
        #  Long stuff to process
    
    
    process.delay(3)
    

    最后你需要rqworker 来启动worker:

    rqworker

    您可以查看RQ docs 了解更多信息。 RQ 专为简单的长时间运行的进程而设计。

    芹菜

    Celery 比较复杂,具有大量功能,如果您不熟悉作业队列和分布式处理方法,不推荐使用。

    绿叶

    Greenlets 有开关。让您在长时间运行的进程之间切换。 您可以使用 greenlets 来运行进程。好处是你不需要 Redis 和其他 worker,相反你必须重新设计你的函数来兼容:

    from greenlet import greenlet
    
    def test1():
        print 12
        gr2.switch()
        print 34
    
    def test2():
        print 56
        gr1.switch()
        print 78
    
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()
    

    【讨论】:

      【解决方案4】:

      您的方法很好,并且完全可以工作,但是当存在广泛接受的解决方案(即 celery)时,为什么要为 Python Web 应用程序重新发明后台工作程序。

      在我信任任何家庭滚动代码来完成如此重要的任务之前,我需要进行大量测试。

      此外,celery 还为您提供任务持久性等功能,以及在多台机器上分配工作人员的能力。

      【讨论】:

        猜你喜欢
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-23
        • 1970-01-01
        • 2012-11-26
        • 1970-01-01
        • 2019-04-27
        相关资源
        最近更新 更多