Многопроцессорный пул Python внутри процесса демона - PullRequest
3 голосов
/ 29 июня 2011

Я открыл вопрос для этой проблемы и не получил достаточно подробного ответа для решения проблемы (скорее всего из-за недостатка строгости в объяснении моих проблем, что я и пытаюсь исправить): Зомбипроцесс в демоне многопроцессорной обработки python

Я пытаюсь реализовать демон 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)

Я не устанавливаю 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

    ...

То же самое, я не перенаправляю 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)

    ...

Здесь идея заключается в том, что мне нужно не только убить процессно и убирать в бассейне.self.pool = None - это просто случайная попытка решить проблемы, которые не сработали.Сначала я подумал, что это проблема с детьми-зомби, которая возникала, когда у меня были self.pool.close() и self.pool.join() внутри цикла while с 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]

Различные местоположения объектов подсказывают мне, что они не являются одним и тем же пулом и что один из них, вероятно, зомби?

После 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

Я пытался переместить self.pool = Pool(processes=4) в несколько разных мест.Если он перемещен в start()' or daemonize () methods, print, то self.pool` выдаст исключение, сообщающее, что это NoneType.Кроме того, местоположение, кажется, изменяет количество процессов, которые будут появляться в зомби.

В настоящее время я не добавил функциональность для запуска чего-либо через рабочих.Кажется, моя проблема полностью связана с правильной настройкой пула работников.Буду признателен за любую информацию, которая приведет к решению этой проблемы, или за советы по созданию службы демона, которая использует пул рабочих для выполнения серии команд с использованием Popen.Так как я не зашел так далеко, я не знаю, с какими проблемами я столкнусь впереди.Я думаю, что мне, возможно, просто нужно написать свой собственный пул, но если есть хороший трюк, чтобы заставить пул работать здесь, это было бы удивительно.

1 Ответ

1 голос
/ 30 июня 2011

Решение состоит в том, чтобы поместить self.pool = Pool(process=4) в качестве последней строки метода daemonize. В противном случае пул теряется где-то (возможно, в fork с). Тогда к пулу можно получить доступ внутри метода run, который перегружен приложением, которое вы хотите демонизировать. Однако доступ к пулу в методе stop невозможен, и это может привести к исключениям NoneType. Я считаю, что есть более элегантное решение, но это работает, и это все, что у меня есть на данный момент. Если я хочу, чтобы stop не работал, когда пул все еще работает, мне нужно будет добавить дополнительные функции к run и какой-либо форме сообщения, но в данный момент я не обеспокоен этим.

...