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

后端 未结 13 1167
名媛妹妹
名媛妹妹 2020-11-27 11:48

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 che

相关标签:
13条回答
  • 2020-11-27 12:04

    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:

    • https://pypi.python.org/pypi/psutil
    • https://github.com/giampaolo/psutil
    • http://pythonhosted.org/psutil/#psutil.pid_exists
    0 讨论(0)
  • 2020-11-27 12:04

    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
    
    0 讨论(0)
  • 2020-11-27 12:07

    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.

    0 讨论(0)
  • 2020-11-27 12:07

    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
    
    0 讨论(0)
  • 2020-11-27 12:15

    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
    
    0 讨论(0)
  • 2020-11-27 12:15

    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
    0 讨论(0)
提交回复
热议问题