Python 在芹菜中,当工人即将停工时,如何中止正在运行的任务?

Python 在芹菜中,当工人即将停工时,如何中止正在运行的任务?,python,multithreading,python-3.x,celery,Python,Multithreading,Python 3.x,Celery,我正在用芹菜做一项长时间的工作。该任务将使用subprocess.Popen创建子流程。为了使任务可中止,我编写以下代码: from celery.contrib import abortable @task(bind=True, base=abortable.AbortableTask) def my_task(self, *args): p = subprocess.Popen([...]) while True: try: p.wa

我正在用芹菜做一项长时间的工作。该任务将使用
subprocess.Popen
创建子流程。为了使任务可中止,我编写以下代码:

from celery.contrib import abortable

@task(bind=True, base=abortable.AbortableTask)
def my_task(self, *args):
    p = subprocess.Popen([...])
    while True:
        try:
            p.wait(1)
        except subprocess.TimeoutExpired:
            if self.is_aborted():
                p.terminate()
                return
        else:
            break
    # Other codes...
我在我的控制台上试过,效果很好。但当我决定按Ctrl+C关闭工作进程时,程序会打印出“工作进程:热关机(MainProcess)”,并被阻塞很长时间,这不是我所期望的在员工即将离职时,任务流产似乎不会发生。

从文档中我知道,如果我想中止任务,我应该使用任务id手动实例化一个
AbortableAsyncResult
,并调用它的
.abort()
方法。
但是我找不到放置此代码的地方,因为它需要所有正在运行的任务的id,我无法访问这些任务

那么,当工作人员即将关闭时,如何为所有正在运行的任务调用
.abort()
?或者有其他选择吗


我将芹菜4.1.0与Python3.6.2结合使用。

您可以使用芹菜4.1.0。只需获取所有正在运行的任务并调用.abort()。

受@Ishaan答案的启发,我自己解决了它,使用以下代码:

def my_task(*args):
    p = None
    from celery.platforms import signals

    def int_handler(signum, frame):
        if p is not None:
            p.kill()
            p.wait()

    signals['INT'] = int_handler

    p = subprocess.Popen([...])
    p.wait()
    # Other codes...
解决方案基于以下考虑:

  • 任务的内部范围是我能找到的每个工作人员执行任务的唯一地方
  • 在任务内部,我可以轻松访问创建的子流程
  • SIGINT信号不由芹菜工人处理,因此它不会覆盖芹菜的默认行为
  • 一个工作者一次将运行一个任务,因此这种注册是安全的

谢谢您的回答。但我对如何获取运行任务列表感到困惑。文档中说我应该使用
app.control.inspect().active()
,但无论放置哪个信号处理程序,它都会不断返回
None
。您可以尝试。如果这也不起作用,也许你可以使用任务信号来维护一个正在运行的任务列表。它也不起作用。。。我刚刚阅读了它的源代码,发现inspect服务在关闭期间不可用。您对执行此类任务有何建议?在正常(热)关机情况下,工作人员从不终止任务。如果您不需要执行任何清理过程,那么Ctrl+C两次将导致冷关机,工作进程将终止所有正在运行的任务。