Дождитесь окончания определенного процесса (зная «pid») - PullRequest
14 голосов
/ 04 октября 2011

У меня есть это:

def get_process():
    pids = []
    process = None
    for i in os.listdir('/proc'):
        if i.isdigit():
            pids.append(i)

    for pid in pids:
        proc = open(os.path.join('/proc', pid, 'cmdline'), 'r').readline()
        if proc == "Something":
            process = pid

    return process          

def is_running(pid):
    return os.path.exists("/proc/%s" % str(pid))

Тогда я делаю это:

process = get_process()
if process == None:
    #do something
else:
    #Wait until the process end
    while is_running(process):
        pass

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

Отказ от ответственности: процесс не является дочерним процессом

Ответы [ 4 ]

14 голосов
/ 05 октября 2011

Я на самом деле не программист на Python, но, очевидно, у Python есть os.waitpid().Это должно потреблять меньше процессорного времени и обеспечивать гораздо более быстрый отклик, чем, скажем, попытка уничтожить процесс с интервалом в четверть секунды.


Добавление: Как отмечает Нико, os.waitpid() может не работать, если процесс не является дочерним по отношению к текущему процессу.В этом случае использование os.kill(pid, 0) действительно может быть лучшим решением.Обратите внимание, что, как правило, существует три вероятных результата вызова os.kill() для процесса:

  1. Если процесс существует и принадлежит вам, вызов завершается успешно.
  2. Еслипроцесс существует, но принадлежит другому пользователю, он выдает OSError с атрибутом errno, установленным в errno.EPERM.
  3. Если процесс не существует, он выдает OSError с атрибутом errno, установленным в errno.ESRCH.

Таким образом, чтобы надежно проверить, существует ли процесс, вы должны сделать что-то вроде

def is_running(pid):        
    try:
        os.kill(pid, 0)
    except OSError as err:
        if err.errno == errno.ESRCH:
            return False
    return True
1 голос
/ 04 октября 2011

Поскольку этот метод будет работать только на linux, для поддержки linux / osx вы можете сделать:

import time
import os

def is_running(pid):
    stat = os.system("ps -p %s &> /dev/null" % pid)
    return stat == 0

pid = 64463

while is_running(pid):
    time.sleep(.25)

Редактировать - в комментариях TMC о чрезмерных процессах

Ссылка: Как проверить, существует ли процесс с данным pid в Python?

Разве это не будет использовать меньше ресурсов (я не проверял), чем листинг в файловой системе и открытиеFDs ко всем результатам?

import time
import os

def is_running(pid):        
    try:
        os.kill(pid, 0)
    except OSError:
        return False

    return True

pid = 64463

while is_running(pid):
    time.sleep(.25)
1 голос
/ 04 октября 2011

import time, затем используйте time.sleep(#):

import time
process = get_process()
if process == None:
    #do something
else:
    #Wait until the process end
    while is_running(process):
        time.sleep(0.25)

У меня также есть та же самая функция в нескольких моих записях, чтобы прочитать /proc/#/cmdline, чтобы проверить PID.

0 голосов
/ 05 октября 2018

Простой и надежный способ сделать это с помощью Python - получить список PID с помощью psutil, а затем проверить, находится ли ваш PID в этом списке работающих PID:

import psutil

def check_pid(pid):

    if int(pid) in psutil.pids(): ## Check list of PIDs
        return True ## Running
    else:
        return False ## Not Running

Чтобы использовать его,просто запустите его в простом цикле while.

pid = 1000
running = True

while running == True:
    running = check_pid(int(pid))
    (Do stuff *until* PID ends)

(Do stuff *after* PID ends)

Или вы можете просто поместить все это в одну функцию ...

def pause_while_running(pid):

    running = True

    while running:
        if int(pid) not in psutil.pids():
            running = False
        time.sleep(5)

и использовать как

pause_while_running(pid)
(do stuff after PID ended)
...