如何正确地动态关闭PythonRQ工作进程?

如何正确地动态关闭PythonRQ工作进程?,python,asynchronous,process,signals,Python,Asynchronous,Process,Signals,使用,我们试图动态管理工作进程。我们使用定制的辅助脚本,其(简化形式)如下所示: 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() 我们对关闭工人特别感兴趣。我们主要关心的

使用,我们试图动态管理工作进程。我们使用定制的辅助脚本,其(简化形式)如下所示:

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()
我们对关闭工人特别感兴趣。我们主要关心的是如何优雅地关闭一个工人,使当前的工作能够在关闭之前完成。相应的
Worker
对象上的
request\u stop(…)
信号处理程序似乎执行了我们需要的操作,但似乎没有办法(至少据我所知)发出它,除非通过在终端中运行的Worker进程上按
CTRL+C

在我看来,有两种可能的解决方案(肯定会有更多)——按优先顺序排列:

  • 通过编程,使用
    rq
    库,将信号发送到
    request\u stop
    ,从而触发正常关机
  • 以某种方式获取正确进程的pid(不确定是workhorse进程还是worker listener进程),并使用其他方法向该进程发送适当的信号。我们有一些方法可以做到这一点,但这很可能需要更多的工作,并为我希望忽略的问题引入其他变量(例如,使用
    Fabric
    运行远程命令或类似的内容)

  • 如果有更好的方法来解决这个问题,或者有不同的替代方案来实现相同的目标,我将非常感谢您的建议。

    选项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
    
    在主脚本中,按照@Borys的建议获取worker PID,发送热停止请求,然后取消链接(“path/to/worker\u NAME.%d”%worker\u PID),以确保正常关闭:)


    但这只适用于运行无限循环的工人。如果工作进程调用的东西甚至会阻塞普通的顺序一次性作业,那么您必须进一步跟踪可能的阻塞例程以从那里解决,例如应用某种超时策略。

    如果您需要PID,实际上可以从w.PID获取它