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

Viewed 141345

Is there a way to check to see if a pid corresponds to a valid process? I'm getting a pid from a different source other than from os.getpid() and I need to check to see if a process with that pid doesn't exist on the machine.

I need it to be available in Unix and Windows. I'm also checking to see if the PID is NOT in use.

14 Answers

Sending signal 0 to a pid will raise an OSError exception if the pid is not running, and do nothing otherwise.

import os

def check_pid(pid):        
    """ Check For the existence of a unix pid. """
    try:
        os.kill(pid, 0)
    except OSError:
        return False
    else:
        return True

In Python 3.3+, you could use exception names instead of errno constants. Posix version:

import os

def pid_exists(pid): 
    if pid < 0: return False #NOTE: pid == 0 returns True
    try:
        os.kill(pid, 0) 
    except ProcessLookupError: # errno.ESRCH
        return False # No such process
    except PermissionError: # errno.EPERM
        return True # Operation not permitted (i.e., process exists)
    else:
        return True # no error, we can send a signal to the process

Look here for windows-specific way of getting full list of running processes with their IDs. It would be something like

from win32com.client import GetObject
def get_proclist():
    WMI = GetObject('winmgmts:')
    processes = WMI.InstancesOf('Win32_Process')
    return [process.Properties_('ProcessID').Value for process in processes]

You can then verify pid you get against this list. I have no idea about performance cost, so you'd better check this if you're going to do pid verification often.

For *NIx, just use mluebke's solution.

The following code works on both Linux and Windows, and not depending on external modules

import os
import subprocess
import platform
import re

def pid_alive(pid:int):
    """ Check For whether a pid is alive """


    system = platform.uname().system
    if re.search('Linux', system, re.IGNORECASE):
        try:
            os.kill(pid, 0)
        except OSError:
            return False
        else:
            return True
    elif re.search('Windows', system, re.IGNORECASE):
        out = subprocess.check_output(["tasklist","/fi",f"PID eq {pid}"]).strip()
        # b'INFO: No tasks are running which match the specified criteria.'

        if re.search(b'No tasks', out, re.IGNORECASE):
            return False
        else:
            return True
    else:
        raise RuntimeError(f"unsupported system={system}")

It can be easily enhanced in case you need

  1. other platforms
  2. other language

I found that this solution seems to work well in both windows and linux. I used psutil to check.

import psutil
import subprocess
import os
p = subprocess.Popen(['python', self.evaluation_script],stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

pid = p.pid

def __check_process_running__(self,p):
    if p is not None:
        poll = p.poll()
        if poll == None:
            return True
    return False
    
def __check_PID_running__(self,pid):
    """
        Checks if a pid is still running (UNIX works, windows we'll see)
        Inputs:
            pid - process id
        returns:
            True if running, False if not
    """
    if (platform.system() == 'Linux'):
        try:
            os.kill(pid, 0)
            if pid<0:               # In case code terminates
                return False
        except OSError:
            return False 
        else:
            return True
    elif (platform.system() == 'Windows'):
        return pid in (p.pid for p in psutil.process_iter())

Another option for Windows is through the pywin32 package:

pid in win32process.EnumProcesses()

The win32process.EnumProcesses() returns PIDs for currently running processes.

I'd say use the PID for whatever purpose you're obtaining it and handle the errors gracefully. Otherwise, it's a classic race (the PID may be valid when you check it's valid, but go away an instant later)

Related