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

PythonProcessPid

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

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

Solution 2 - Python

Have a look at the psutil module:

> psutil (python system and process utilities) is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network) in Python. [...] It currently supports Linux, Windows, OSX, FreeBSD and Sun Solaris, both 32-bit and 64-bit architectures, with Python versions from 2.6 to 3.4 (users of Python 2.4 and 2.5 may use 2.1.3 version). PyPy is also known to work.

It has a function called pid_exists() that you can use to check whether a process with the given pid exists.

Here's an example:

import psutil
pid = 12345
if psutil.pid_exists(pid):
    print("a process with pid %d exists" % pid)
else:
    print("a process with pid %d does not exist" % pid)

For reference:

Solution 3 - Python

mluebke code is not 100% correct; kill() can also raise EPERM (access denied) in which case that obviously means a process exists. This is supposed to work:

(edited as per Jason R. Coombs comments)

import errno
import os

def pid_exists(pid):
    """Check whether pid exists in the current process table.
    UNIX only.
    """
    if pid < 0:
        return False
    if pid == 0:
        # According to "man 2 kill" PID 0 refers to every process
        # in the process group of the calling process.
        # On certain systems 0 is a valid PID but we have no way
        # to know that in a portable fashion.
        raise ValueError('invalid PID 0')
    try:
        os.kill(pid, 0)
    except OSError as err:
        if err.errno == errno.ESRCH:
            # ESRCH == No such process
            return False
        elif err.errno == errno.EPERM:
            # EPERM clearly means there's a process to deny access to
            return True
        else:
            # According to "man 2 kill" possible error values are
            # (EINVAL, EPERM, ESRCH)
            raise
    else:
        return True

You can't do this on Windows unless you use pywin32, ctypes or a C extension module. If you're OK with depending from an external lib you can use psutil:

>>> import psutil
>>> psutil.pid_exists(2353)
True

Solution 4 - Python

The answers involving sending 'signal 0' to the process will work only if the process in question is owned by the user running the test. Otherwise you will get an OSError due to permissions, even if the pid exists in the system.

In order to bypass this limitation you can check if /proc/<pid> exists:

import os

def is_running(pid):
    if os.path.isdir('/proc/{}'.format(pid)):
        return True
    return False

This applies to linux based systems only, obviously.

Solution 5 - Python

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.

Solution 6 - Python

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

Solution 7 - Python

Building upon ntrrgc's I've beefed up the windows version so it checks the process exit code and checks for permissions:

def pid_exists(pid):
	"""Check whether pid exists in the current process table."""
	if os.name == 'posix':
		import errno
		if pid < 0:
			return False
		try:
			os.kill(pid, 0)
		except OSError as e:
			return e.errno == errno.EPERM
		else:
			return True
	else:
		import ctypes
		kernel32 = ctypes.windll.kernel32
		HANDLE = ctypes.c_void_p
		DWORD = ctypes.c_ulong
		LPDWORD = ctypes.POINTER(DWORD)
		class ExitCodeProcess(ctypes.Structure):
			_fields_ = [ ('hProcess', HANDLE),
				('lpExitCode', LPDWORD)]
		
		SYNCHRONIZE = 0x100000
		process = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
		if not process:
			return False
		
		ec = ExitCodeProcess()
		out = kernel32.GetExitCodeProcess(process, ctypes.byref(ec))
		if not out:
			err = kernel32.GetLastError()
			if kernel32.GetLastError() == 5:
				# Access is denied.
				logging.warning("Access is denied to get pid info.")
			kernel32.CloseHandle(process)
			return False
		elif bool(ec.lpExitCode):
			# print ec.lpExitCode.contents
			# There is an exist code, it quit
			kernel32.CloseHandle(process)
			return False
		# No exit code, it's running.
		kernel32.CloseHandle(process)
		return True

Solution 8 - Python

Combining Giampaolo Rodolà's answer for POSIX and mine for Windows I got this:

import os
if os.name == 'posix':
    def pid_exists(pid):
        """Check whether pid exists in the current process table."""
        import errno
        if pid < 0:
            return False
        try:
            os.kill(pid, 0)
        except OSError as e:
            return e.errno == errno.EPERM
        else:
            return True
else:
    def pid_exists(pid):
        import ctypes
        kernel32 = ctypes.windll.kernel32
        SYNCHRONIZE = 0x100000

        process = kernel32.OpenProcess(SYNCHRONIZE, 0, pid)
        if process != 0:
            kernel32.CloseHandle(process)
            return True
        else:
            return False

Solution 9 - Python

This will work for Linux, for example if you want to check if banshee is running... (banshee is a music player)

import subprocess

def running_process(process):
    "check if process is running. < process > is the name of the process."

    proc = subprocess.Popen(["if pgrep " + process + " >/dev/null 2>&1; then echo 'True'; else echo 'False'; fi"], stdout=subprocess.PIPE, shell=True)

    (Process_Existance, err) = proc.communicate()
    return Process_Existance

# use the function
print running_process("banshee")

Solution 10 - Python

In Windows, you can do it in this way:

import ctypes
PROCESS_QUERY_INFROMATION = 0x1000
def checkPid(pid):
    processHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_INFROMATION, 0,pid)
    if processHandle == 0:
        return False
    else:
        ctypes.windll.kernel32.CloseHandle(processHandle)
    return True

First of all, in this code you try to get a handle for process with pid given. If the handle is valid, then close the handle for process and return True; otherwise, you return False. Documentation for OpenProcess: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

Solution 11 - Python

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

Solution 12 - Python

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

Solution 13 - Python

Another option for Windows is through the pywin32 package:

pid in win32process.EnumProcesses()

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

Solution 14 - Python

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEvan FosmarkView Question on Stackoverflow
Solution 1 - PythonmluebkeView Answer on Stackoverflow
Solution 2 - PythonmoooeeeepView Answer on Stackoverflow
Solution 3 - PythonGiampaolo RodolàView Answer on Stackoverflow
Solution 4 - PythonOmer DaganView Answer on Stackoverflow
Solution 5 - PythonAlexander LebedevView Answer on Stackoverflow
Solution 6 - PythonjfsView Answer on Stackoverflow
Solution 7 - PythonspeedplaneView Answer on Stackoverflow
Solution 8 - PythonAliciaView Answer on Stackoverflow
Solution 9 - PythonBARSPINView Answer on Stackoverflow
Solution 10 - PythonAndreiView Answer on Stackoverflow
Solution 11 - PythonoldprideView Answer on Stackoverflow
Solution 12 - PythonPatView Answer on Stackoverflow
Solution 13 - PythonROJIView Answer on Stackoverflow
Solution 14 - PythonDamien_The_UnbelieverView Answer on Stackoverflow