Wait until a certain process (knowing the "pid") end

Niko picture Niko · Oct 4, 2011 · Viewed 16.2k times · Source

I have this:

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))

Then i do this:

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

I think this is not the best way to wait for the process to terminate, there must be some function wait or something, but i can't find it.

Disclaimer: The process is not a child process

Answer

Ilmari Karonen picture Ilmari Karonen · Oct 4, 2011

I'm not really a Python programmer, but apparently Python does have os.waitpid(). That should consume less CPU time and provide a much faster response than, say, trying to kill the process at quarter-second intervals.


Addendum: As Niko points out, os.waitpid() may not work if the process is not a child of the current process. In that case, using os.kill(pid, 0) may indeed be the best solution. Note that, in general, there are three likely outcomes of calling os.kill() on a process:

  1. If the process exists and belongs to you, the call succeeds.
  2. If the process exists but belong to another user, it throws an OSError with the errno attribute set to errno.EPERM.
  3. If the process does not exist, it throws an OSError with the errno attribute set to errno.ESRCH.

Thus, to reliably check whether a process exists, you should do something like

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