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

17,830

Solution 1

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

Solution 2

Since that method would only work on linux, for linux/osx support, you could do:

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)

Edit - Per tMc's comment about excessive processes

Referencing: How to check if there exists a process with a given pid in Python?

Wouldn't this use less resources (I havent tested), than listing on the filesystem and opening FDs to all the results?

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)

Solution 3

import time, then use 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)

I also have that exact same function in several of my scrips to read through /proc/#/cmdline to check for a PID.

Share:
17,830
Niko
Author by

Niko

Updated on June 12, 2022

Comments

  • Niko
    Niko almost 2 years

    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

  • Niko
    Niko over 12 years
    This prevents the program uses 100% of one of the cores of my cpu, i hadnt really noticed that :P but anyway there should be some function, however I think this solution isn't so bad.
  • chown
    chown over 12 years
    With threading you could do somewhat better, but it gets really overcomplicated for this simple of a task and threads have expensive overhead.
  • tMC
    tMC over 12 years
    this will spawn a subshell, which will spawn a process for the ps command, creating 8 processes a second.
  • jdi
    jdi over 12 years
    What if the call to os.system were replaced with the method he uses here ?
  • tMC
    tMC over 12 years
    Thats better than stating /proc/<pid> IMHO.
  • Niko
    Niko over 12 years
    That only works for a child process. It would be great if this works for any process.
  • Niko
    Niko over 12 years
    It seems a better idea, i'll use it
  • dbn
    dbn almost 10 years
    This won't work on Windows - the kill signal unconditionally kills the process sent the signal (docs).
  • alper
    alper almost 4 years
    Should I also write is_running() inside a try/except?
  • jdi
    jdi almost 4 years
    @alper no that isn't necessary. The kill is the one to likely raise if the pid is gone. The running check should not be exceptional.