Wait until a certain process (knowing the "pid") end
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:
- If the process exists and belongs to you, the call succeeds.
- If the process exists but belong to another user, it throws an
OSError
with theerrno
attribute set toerrno.EPERM
. - If the process does not exist, it throws an
OSError
with theerrno
attribute set toerrno.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.
Niko
Updated on June 12, 2022Comments
-
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 over 12 yearsThis 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 over 12 yearsWith threading you could do somewhat better, but it gets really overcomplicated for this simple of a task and threads have expensive overhead.
-
tMC over 12 yearsthis will spawn a subshell, which will spawn a process for the ps command, creating 8 processes a second.
-
jdi over 12 yearsWhat if the call to os.system were replaced with the method he uses here ?
-
tMC over 12 yearsThats better than stating /proc/<pid> IMHO.
-
Niko over 12 yearsThat only works for a child process. It would be great if this works for any process.
-
Niko over 12 yearsIt seems a better idea, i'll use it
-
dbn almost 10 yearsThis won't work on Windows - the kill signal unconditionally kills the process sent the signal (docs).
-
alper almost 4 yearsShould I also write
is_running()
inside atry/except
? -
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.