Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 退出守护进程时出现问题_Python_Daemon_Multiprocessing - Fatal编程技术网

Python 退出守护进程时出现问题

Python 退出守护进程时出现问题,python,daemon,multiprocessing,Python,Daemon,Multiprocessing,我正在编写一个守护程序,它会生成其他几个子进程。在我运行stop脚本之后,当主进程打算退出时,它会继续运行,这让我很困惑 import daemon, signal from multiprocessing import Process, cpu_count, JoinableQueue from http import httpserv from worker import work class Manager: """ This manager starts the htt

我正在编写一个守护程序,它会生成其他几个子进程。在我运行
stop
脚本之后,当主进程打算退出时,它会继续运行,这让我很困惑

import daemon, signal
from multiprocessing import Process, cpu_count, JoinableQueue
from http import httpserv
from worker import work

class Manager:
    """
    This manager starts the http server processes and worker
    processes, creates the input/output queues that keep the processes
    work together nicely.
    """
    def __init__(self):
        self.NUMBER_OF_PROCESSES = cpu_count()

    def start(self):
        self.i_queue = JoinableQueue()
        self.o_queue = JoinableQueue()

        # Create worker processes
        self.workers = [Process(target=work,
                                args=(self.i_queue, self.o_queue))
                        for i in range(self.NUMBER_OF_PROCESSES)]
        for w in self.workers:
            w.daemon = True
            w.start()

        # Create the http server process
        self.http = Process(target=httpserv, args=(self.i_queue, self.o_queue))
        self.http.daemon = True
        self.http.start()

        # Keep the current process from returning
        self.running = True
        while self.running:
            time.sleep(1)

    def stop(self):
        print "quiting ..."

        # Stop accepting new requests from users
        os.kill(self.http.pid, signal.SIGINT)

        # Waiting for all requests in output queue to be delivered
        self.o_queue.join()

        # Put sentinel None to input queue to signal worker processes
        # to terminate
        self.i_queue.put(None)
        for w in self.workers:
            w.join()
        self.i_queue.join()

        # Let main process return
        self.running = False


import daemon

manager = Manager()
context = daemon.DaemonContext()
context.signal_map = {
        signal.SIGHUP: lambda signum, frame: manager.stop(),
        }

context.open()
manager.start()

stop
脚本只是一行的
os.kill(pid,signal.SIGHUP)
,但是在那之后,子进程(工作进程和http服务器进程)很好地结束了,但是主进程只是停留在那里,我不知道是什么阻止了它返回。

我尝试了另一种方法,这似乎有效(注意,我去掉了代码的守护进程部分,因为我没有安装该模块)

一个警告是signal.pause()将取消任何信号的暂停,因此您可能需要相应地更改代码

编辑:

以下内容对我来说很好:

import daemon
import signal
import time

class Manager:
    """
    This manager starts the http server processes and worker
    processes, creates the input/output queues that keep the processes
    work together nicely.
    """
    def __init__(self):
        self.NUMBER_OF_PROCESSES = 5

    def start(self):

       # all your code minus the loop

       print "waiting to die"
       self.running = 1
       while self.running:
           time.sleep(1)

       print "quit"



    def stop(self):
        print "quitting ..."

        # all your code minus self.running

        self.running = 0


manager = Manager()

context = daemon.DaemonContext()
context.signal_map = {signal.SIGHUP : lambda signum, frame: manager.stop()}

context.open()
manager.start()

您使用的是哪一版本的python?

您创建了http服务器进程,但没有加入它。如果您不是执行一个
os.kill()
来停止http服务器进程,而是向它发送一个停止处理哨兵(
None
,就像发送给工作人员一样),然后执行一个
self.http.join()
,会发生什么情况

更新:您还需要为每个工作人员向输入队列发送一次
None
哨兵。您可以尝试:

    for w in self.workers:
        self.i_queue.put(None)
    for w in self.workers:
        w.join()
注意:您需要两个循环的原因是,如果您将
None
放入执行
join()
的同一个循环中的队列,那么
None
可能会被
w
以外的工作人员拾取,因此打开
w
将导致调用方阻塞

您没有为worker或http服务器显示代码,因此我假设这些在调用task_done等方面表现良好,并且每个worker在看到
None
时都会退出,而不会从输入队列中删除更多内容


另外,请注意,至少有
JoinableQueue.task_done()
,它可能会咬到您。

您是否看到“退出…”打印出来?我按原样尝试了你的代码,但没有守护程序模块,它对我有效。你能给我一个链接到你的守护程序模块版本吗?谷歌搜索揭示了一些选择。很抱歉我反应太晚,对于我使用@grieve的守护程序模块,我从来没有看到“退出…”,因为stdout和stderr在被守护时被重定向到一个日志文件,但即使在重定向的文件中,我也没有看到它。@Joshua:你是对的,我早期的回答不值得赏金,我已经删除了它。但是,我认为否决是不公平的。我不介意失去代表,我可以接受;我只是认为否决是不对的在回答这个问题之前,答案是正确的。给我留下评论就足够了(无论如何,这就是我来这里的原因).既然如此明显地没有告诉你,如果悬赏是放在你回答的问题上的,我希望你不是在暗示我故意等待悬赏在我站起来之前落地。我自己不会手动处理信号,而是在代码中的while true循环确实是self.http.join()中处理守护进程模块,但有一个进程没有退出,然后我将其替换为while true循环,该进程仍然没有退出:(请参阅我的更新。带有我的更改的脚本的修改版本将正确终止,至少在我的环境中是这样)。
    for w in self.workers:
        self.i_queue.put(None)
    for w in self.workers:
        w.join()