Comment vérifier s'il existe un processus avec un pid en Python?

Est-il un moyen de vérifier pour voir si un pid correspond à un processus valide? Je reçois un pid d'une autre source que os.getpid() et j'ai besoin de vérifier pour voir si un processus avec CE pid n'existe pas sur la machine.

j'en ai besoin pour être disponible sous Unix et Windows. Je vérifie aussi si le PID n'est pas utilisé.

79
demandé sur Omer Dagan 2009-02-20 07:22:43

11 réponses

envoyer le signal 0 à un pid soulèvera une exception OSError si le pid ne tourne pas, et ne fera rien d'autre.

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
127
répondu mluebke 2010-11-08 18:52:32

mluebke code n'est pas correct à 100%; kill() peut aussi poser des EPERM (accès refusé) et dans ce cas cela signifie évidemment l'existence d'un processus. C'est censé marcher:

(édité par Jason R. Combes commentaires)

import errno
import os
import sys

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

vous ne pouvez pas faire cela sur Windows à moins que vous n'utilisiez pywin32, ctypes ou un module d'extension C. Si vous êtes D'accord avec en fonction d'un lib externe, vous pouvez utiliser psutil :

>>> import psutil
>>> psutil.pid_exists(2353)
True
51
répondu Giampaolo Rodolà 2014-12-11 01:08:16

regardez le psutil module:

psutil (Python system and process utilities) est une bibliothèque multi-plateforme pour extraire des informations sur les processus d'exécution et l'utilisation du système (CPU, mémoire, disques, réseau) en Python. [...] Il supporte actuellement Linux , Windows , OSX , FreeBSD et Sun Solaris , à la fois 32-bit et 64-bit architectures, avec des versions Python de 2.6 à 3.4 (les utilisateurs de Python 2.4 et 2.5 peuvent utiliser la version 2.1.3). PyPy est également connu pour travailler.

Il a une fonction appelée pid_exists() que vous pouvez utiliser pour vérifier si un processus avec le pid existe.

voici un exemple:

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

pour référence:

50
répondu moooeeeep 2015-02-19 07:56:13

les réponses impliquant l'envoi du 'signal 0' au processus ne fonctionneront que si le processus en question appartient à l'utilisateur qui exécute le test . Sinon, vous obtiendrez un OSError dû à permissions , même si le pid existe dans le système.

afin de contourner cette limitation, vous pouvez vérifier si /proc/<pid> existe:

import os

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

cela s'applique uniquement aux systèmes basés sur linux, évidemment.

12
répondu Omer Dagan 2018-09-26 14:51:24

Look ici pour windows spécifique de la façon d'obtenir la liste complète des processus en cours d'exécution avec leur Id. Ce serait quelque chose comme

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]

vous pouvez alors vérifier les pid que vous obtenez par rapport à cette liste. Je n'ai aucune idée du coût de la performance, donc vous feriez mieux de vérifier ça si vous allez faire la vérification pid souvent.

pour * NIx, il suffit d'utiliser la solution de mluebke.

6
répondu Alexander Lebedev 2009-02-20 07:20:11

en Python 3.3+, vous pouvez utiliser des noms d'exception au lieu de constantes errno. version Posix :

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
6
répondu jfs 2013-11-25 07:12:53

en S'appuyant sur la version windows de ntrrgc, j'ai vérifié le code de sortie du processus et les 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
6
répondu speedplane 2014-05-01 14:06:04

combinant réponse de Giampaolo Rodolà pour POSIX et mine Pour Windows j'ai obtenu ceci:

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
4
répondu Alicia 2017-05-23 11:47:30

Dans Windows, vous pouvez le faire de cette façon:

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

tout d'abord, dans ce code vous essayez d'obtenir une poignée pour le processus avec pid donné. Si la poignée est valide, alors fermez la poignée pour process et retournez True; sinon, vous retournez False. Documentation pour le Processusouvert: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

2
répondu Andrei 2015-01-29 12:26:47

cela fonctionnera pour Linux, par exemple si vous voulez vérifier si banshee est en cours d'exécution... (banshee est un lecteur de musique)

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")
2
répondu BARSPIN 2015-05-12 09:32:35

je dirais d'utiliser le PID pour quelque chose que vous l'obtenez et de gérer les erreurs avec élégance. Sinon, c'est une course classique (le PID peut être valide quand vous le vérifiez, mais partez un instant plus tard)

-2
répondu Damien_The_Unbeliever 2009-02-20 07:39:21