Existe-t-il un moyen de vérifier si un pid correspond à un processus valide? Je reçois un pid d'une autre source que celle de os.getpid()
et je dois vérifier 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 également si le PID n'est PAS utilisé.
L'envoi du signal 0 à un pid lève une exception OSError si le pid n'est pas en cours d'exécution et ne fait rien sinon.
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
Regardez le module psutil
:
psutil (utilitaires système et processus python) est une bibliothèque multiplate-forme permettant de récupérer des informations sur les processus en cours d'exécution et 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 bits et ) Architectures 64 bits , avec Python versions 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 fonctionner.
Il a une fonction appelée pid_exists()
que vous pouvez utiliser pour vérifier si un processus avec le pid donné 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:
le code mluebke n'est pas correct à 100%; kill () peut également déclencher EPERM (accès refusé), auquel cas il est évident qu'un processus existe. Ceci est censé fonctionner:
(édité selon les commentaires de Jason R. Coombs)
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 le faire sous Windows que si vous utilisez pywin32, ctypes ou un module d'extension C. Si vous voulez bien dépendre d'une librairie externe, vous pouvez utiliser psutil :
>>> import psutil
>>> psutil.pid_exists(2353)
True
Les réponses impliquant l'envoi du "signal 0" au processus fonctionneront niquement si le processus en question appartient à l'utilisateur exécutant le test. Sinon, vous obtiendrez un OSError
en raison de autorisations , même si le pid existe dans le système.
Pour 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 ne concerne évidemment que les systèmes basés sur Linux.
Regardez ici pour un moyen spécifique à Windows d’obtenir la liste complète des processus en cours 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 le pid que vous obtenez contre cette liste. Je n'ai aucune idée du coût de la performance, vous feriez donc mieux de vérifier cela si vous allez souvent vérifier le pid.
Pour * NIx, utilisez simplement la solution de mluebke.
Dans 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
Sur la base de ntrrgc, j'ai renforcé la version de Windows afin de vérifier le code de sortie du processus et les autorisations:
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
Combinaison la réponse de Giampaolo Rodolà pour POSIX et la mienne pour Windows J'ai 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
Cela fonctionnera sous 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")
Sous 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 un descripteur de processus avec pid donné. Si le descripteur est valide, fermez-le pour le processus et renvoyez True; sinon, vous retournez False. Documentation pour OpenProcess: https://msdn.Microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx