Pregunta

¿Hay alguna manera de verificar si un pid corresponde a un proceso válido?Recibo un pid de una fuente diferente a la de os.getpid() y necesito verificar si no existe un proceso con ese pid en la máquina.

Necesito que esté disponible en Unix y Windows.También estoy comprobando si el PID NO está en uso.

¿Fue útil?

Solución

Envío de señal de 0 a un pid lanzará una excepción OSError si el PID no se está ejecutando, y no hacer nada contrario.

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

Otros consejos

Tener un vistazo a la psutil módulo:

  

psutil (sistema de pitón y los servicios públicos de proceso) es una biblioteca de plataforma cruzada para recuperar información en procesos que se ejecutan y utilización sistema (CPU, memoria, discos, red) en Python. [...] Es compatible actualmente Linux , Windows , OSX , FreeBSD y Sun Solaris , ambos 32 bits y 64 bits arquitecturas, con versiones Python desde 2.6 a 3.4 (usuarios de Python 2.4 y 2.5 puede utilizar la versión 2.1.3). PyPy También se sabe que el trabajo.

Tiene una función llamada pid_exists() que se puede utilizar para comprobar si existe un proceso con el pid.

Este es un ejemplo:

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

Para referencia:

código mluebke no es 100% correcto; matar () también puede elevar EPERM (acceso denegado), en cuyo caso, obviamente, significa que existe un proceso. Esto se supone que funciona:

(editado de acuerdo con los comentarios 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

No se puede hacer esto en Windows a menos que utilice pywin32, ctypes o un módulo de extensión C. Si estás bien con función de un lib externa puede utilizar psutil :

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

Las respuestas que implican enviar 'señal 0' al proceso funcionarán sólo si el proceso en cuestión es propiedad del usuario que ejecuta la prueba.De lo contrario obtendrás un OSError debido a permisos, incluso si el pid existe en el sistema.

Para evitar esta limitación, puede verificar si /proc/<pid> existe:

import os

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

Obviamente, esto se aplica sólo a sistemas basados ​​en Linux.

aquí de manera específica las ventanas de obtener la lista completa de los procesos en ejecución con sus documentos de identidad. Sería algo así como

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]

A continuación, puede verificar pid le aparecerá en esta lista. No tengo ni idea acerca de costo de rendimiento, por lo que Usted debe comprobar esto si va a hacer la verificación pid a menudo.

Para * NIX, sólo tiene que utilizar la solución de mluebke.

En Python 3.3+, se puede usar nombres de excepción en lugar de constantes errno. Posix versión :

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

Sobre la base de ntrrgc He reforzado la versión ventanas, así que comprueba el código de salida del proceso y los controles de permisos:

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

Al combinar la respuesta de Giampaolo Rodolà para POSIX y la mina para Windows tengo esto:

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

En Windows, puede hacerlo de esta manera:

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

En primer lugar, en este código que intenta conseguir una manija para el proceso con pid dada. Si el identificador es válido, a continuación, cierre el asa para el proceso y devolver True; de lo contrario, se vuelve falso. Documentación para OpenProcess: https: / /msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

Esto funciona para Linux, por ejemplo, si desea comprobar si se está ejecutando alma en pena ... (Banshee es un reproductor de música)

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

Yo diría que el uso del PID para cualquier propósito que está obteniendo y controlar los errores con gracia. De lo contrario, se trata de una carrera clásica (el PID puede ser válido cuando se compruebe que es válido, pero vas un instante más tarde)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top