Подождите, пока определенный процесс (зная "pid") не закончится

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

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

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

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

4 ответов


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


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

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

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

def is_running(pid):        
    try:
        os.kill(pid, 0)
    except OSError as err:
        if err.errno == errno.ESRCH:
            return False
    return True

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.


поскольку этот метод будет работать только на 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)

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

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)