如何动态正确关闭Python RQ工作进程?

时间:2013-02-27 18:35:00

标签: python asynchronous process signals

使用Python RQ,我们正在尝试动态管理工作进程。我们使用定制的工作脚本,(简化形式)如下:

from rq import Connection, Worker

queues_to_listen_on = get_queues_to_listen_on()

with Connection(connection = get_worker_connection()):
    w = Worker(queues_to_listen_on)
    w.work()

我们对工人的关闭特别感兴趣。我们主要关注的是如何正常关闭工作人员,以便在关闭之前完成当前工作。相应的request_stop(...)对象上的Worker信号处理程序似乎做了我们需要的事情,但似乎没有办法(至少据我所知)发出它,除非是通过按{{1}关于在终端中运行的工作进程。

正如我所看到的,有两种可能的解决方案(肯定会有更多) - 按优先顺序排列:

  1. 以编程方式,使用CTRL+C库,将信号发送到rq,从而触发正常关机。
  2. 以某种方式获取正确进程的pid(不确定主力进程或工作者监听器进程)并使用其他方法,将适当的信号发送到该进程。我们有一些方法可以做到这一点,但它可能需要更多的工作,并引入其他变量来解决我宁愿被忽略的问题(例如,使用request_stop来运行远程命令或其他东西线)。
  3. 如果有更好的方法来解决这个问题,或者有另一种方法可以达到同样的目标,我将非常感谢您的建议。

1 个答案:

答案 0 :(得分:4)

选项1在设计方面肯定更好。

但是,要解决您必须使用CTRL + C退出流程的特定问题(我也讨厌这样做),您可以为您的员工使用以下策略:

# WORKER_NAME.py
import os

PID = os.getpid()

@atexit.register
def clean_shut():
    print "Clean shut performed"

    try:
        os.unlink("WORKER_NAME.%d" % PID)
    except:
        pass

# Worker main
def main():
    f = open("WORKER_NAME.%d" % PID, "w")
    f.write("Delete this to end WORKER_NAME gracefully")
    f.close()

    while os.path.exists("WORKER_NAME.%d" % PID):
        # Worker working

在你的主脚本中,获取工作者PID为@Borys建议,发送热停止请求,os.unlink("path/to/WORKER_NAME.%d" % worker_PID)以确保正常关闭:)

这只适用于运行无限循环的工作人员。如果工作进程调用阻止普通顺序一次性作业的事情,则必须进一步跟踪可能阻塞的例程以从中解决,例如应用某种超时策略。