Как узнать идентификатор процесса в Python - PullRequest
7 голосов
/ 21 мая 2010

Я работаю с кластерной системой через Linux (www.mosix.org), которая позволяет мне запускать задания и запускать их на разных компьютерах. Работа выполняется так:

mosrun ls &

Это естественным образом создаст процесс и запустит его в фоновом режиме, вернув идентификатор процесса, например:

[1] 29199

Позже он вернется. Я пишу инфраструктуру Python, которая будет выполнять задания и контролировать их. Для этого я хочу запустить задания с помощью программы mosrun, как указано выше, и сохранить идентификатор процесса, который был создан (в данном случае 29199). Естественно, этого нельзя сделать с помощью os.system или commands.getoutput, так как напечатанный идентификатор - это не то, что печатает процесс для вывода ... Любые подсказки?

Редактировать

Поскольку сценарий python предназначен только для первоначального запуска сценария, сценарии должны работать дольше, чем оболочка python. Я предполагаю, что это означает, что процесс mosrun не может быть дочерним процессом сценария. Есть предложения?

Спасибо

Ответы [ 3 ]

3 голосов
/ 21 мая 2010

Использовать subprocess модуль. Popen экземпляры имеют атрибут pid.

2 голосов
/ 22 мая 2010

Похоже, вы хотите убедиться, что дочерний процесс демонизирован - PEP 3143, на который я указываю, документирует и указывает на эталонную реализацию для этого, а также указывает на других.

Как только ваш процесс (все еще выполняется код Python) демонизируется, будь то с помощью средств, предлагаемых в PEP 3143 или других, вы можете os.execl (или другая функция os.exec...) вашего целевого кода - - он запускает указанный целевой код в точно в том же процессе, который мы только что сказали, демонизируется, и поэтому он продолжает демонизироваться, как требуется.

На последнем шаге нельзя использовать subprocess, потому что он должен запускаться в того же самого процесса (daemonized), перекрывая его исполняемый код - именно для этого нужны os.execl и друзья.

Первый шаг, до демонизации, возможно, можно сделать через subprocess, но это несколько неудобно (вам нужно поместить код daemonize-then-os.exec в отдельный .py): чаще всего вам просто хочу os.fork и немедленно демонизировать дочерний процесс.

subprocess довольно удобен в качестве кросс-платформенного способа запуска других процессов, но он не может заменить старый добрый старый подход Unix "fork and exec" для продвинутых целей (таких как демонизация, в данном случае) - поэтому хорошо, что стандартная библиотека Python также позволяет вам делать это с помощью этих функций в модуле os! -)

0 голосов
/ 25 мая 2010

Спасибо всем за помощь. Вот что я сделал в конце, и, кажется, работает нормально. Код использует python-daemon . Может быть, что-то более разумное следует сделать с передачей идентификатора процесса от ребенка к отцу, но это более легкая часть.

import daemon
def run_in_background(command, tmp_dir="/tmp"):

    # Decide on a temp file beforehand
    warnings.filterwarnings("ignore", "tempnam is a potential security")
    tmp_filename = os.tempnam(tmp_dir)

    # Duplicate the process
    pid = os.fork()


    # If we're child, daemonize and run
    if pid == 0:
        with daemon.DaemonContext():
            child_id = os.getpid()
            file(tmp_filename,'w').write(str(child_id))
            sp = command.split(' ')
            os.execl(*([sp[0]]+sp))
    else:
        # If we're a parent, poll for the new file
        n_iter = 0
        while True:
            if os.path.exists(tmp_filename):
                child_id = int(file(tmp_filename, 'r').read().strip())
                break

            if n_iter == 100:
                raise Exception("Cannot read process id from temp file %s" % tmp_filename)
            n_iter += 1

            time.sleep(0.1)

        return child_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...