守护进程内的Python多处理池

Aar*_*son 5 python multithreading pool multiprocessing threadpool

我针对这个问题提出了一个问题,但没有得到足够彻底的答案来解决该问题(很可能是由于在解释我的问题时缺乏严谨性,这正是我试图纠正的):Zombie process in python multiprocessing daemon

我正在尝试实现一个 python 守护进程,它使用工作池来使用Popen. 我从http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/借用了基本守护进程

我只改变了init, daemonize(或同样的start) 和stop方法。以下是该方法的更改init

def __init__(self, pidfile):
#, stdin='/dev/null', stdout='STDOUT', stderr='STDOUT'):
    #self.stdin = stdin
    #self.stdout = stdout
    #self.stderr = stderr
    self.pidfile = pidfile
    self.pool = Pool(processes=4)
Run Code Online (Sandbox Code Playgroud)

我没有设置 stdin、stdout 和 stderr,以便我可以使用 print 语句调试代码。另外,我尝试将此池移动到几个地方,但这是唯一不会产生异常的地方。

以下是该方法的更改daemonize

def daemonize(self):
    ...

    # redirect standard file descriptors
    #sys.stdout.flush()
    #sys.stderr.flush()
    #si = open(self.stdin, 'r')
    #so = open(self.stdout, 'a+')
    #se = open(self.stderr, 'a+', 0)
    #os.dup2(si.fileno(), sys.stdin.fileno())
    #os.dup2(so.fileno(), sys.stdout.fileno())
    #os.dup2(se.fileno(), sys.stderr.fileno())

    print self.pool

    ...
Run Code Online (Sandbox Code Playgroud)

同样的,我没有重定向 io 以便我可以调试。使用此处的打印以便我可以检查泳池位置。

并且stop方法发生变化:

def stop(self):
    ...

    # Try killing the daemon process
    try:
        print self.pool
        print "closing pool"
        self.pool.close()
        print "joining pool"
        self.pool.join()
        print "set pool to None"
        self.pool = None
        while 1:
            print "kill process"
            os.kill(pid, SIGTERM)

    ...
Run Code Online (Sandbox Code Playgroud)

这里的想法是,我不仅需要终止进程,还需要清理池。这self.pool = None只是解决问题的随机尝试,但没有成功。起初,我认为这是僵尸儿童的问题,当我在 while 循环中使用self.pool.close()和时,就会发生这种情况。这是在我决定开始通过. 执行此操作后,我相信守护进程启动和停止时的池不一样。这是一些输出:self.pool.join()os.kill(pid, SIGTERM)print self.pool

me@pc:~/pyCode/jobQueue$ sudo ./jobQueue.py start
<multiprocessing.pool.Pool object at 0x1c543d0>
me@pc:~/pyCode/jobQueue$ sudo ./jobQueue.py stop
<multiprocessing.pool.Pool object at 0x1fb7450>
closing pool
joining pool
set pool to None
kill process
kill process
... [ stuck in infinite loop]
Run Code Online (Sandbox Code Playgroud)

这些物体的不同位置向我表明它们不是同一个池,其中之一可能是僵尸?

之后CTRL+C,这是我得到的ps aux|grep jobQueue

root     21161  0.0  0.0  50384  5220 ?        Ss   22:59   0:00 /usr/bin/python ./jobQueue.py start
root     21162  0.0  0.0      0     0 ?        Z    22:59   0:00 [jobQueue.py] <defunct>
me       21320  0.0  0.0   7624   940 pts/0    S+   23:00   0:00 grep --color=auto jobQueue
Run Code Online (Sandbox Code Playgroud)

我尝试过将其移动self.pool = Pool(processes=4)到许多不同的地方。如果它被移动到start()' ordaemonize() methods,print self.pool` 将抛出一个异常,指出它是 NoneType。另外,位置似乎改变了将弹出的僵尸进程的数量。

目前,我还没有添加通过工作人员运行任何内容的功能。我的问题似乎完全与正确设置工作人员池有关。我将不胜感激任何有助于解决此问题的信息或有关创建守护程序服务的建议,该守护程序服务使用工作人员池来使用Popen. 由于我还没有走到这一步,我不知道我未来会面临什么挑战。我想我可能只需要编写自己的池,但如果有一个很好的技巧可以让池在这里工作,那就太棒了。

Aar*_*son 1

解决方案是将 theself.pool = Pool(process=4)作为方法的最后一行daemonize。否则池最终会在某个地方丢失(可能在forks 中)。run然后,可以在您希望守护进程的应用程序重载的方法内部访问该池。但是,无法在 stop 方法中访问该池,否则会导致 NoneType 异常。我相信有一个更优雅的解决方案,但这是有效的,这就是我现在所拥有的。如果我希望stop在池仍在运行时失败,我将不得不添加额外的功能和run某种形式的消息,但我目前不关心这个。