it-swarm.com.de

Wie überprüfe ich, ob es in Python einen Prozess mit einer bestimmten PID gibt?

Gibt es eine Möglichkeit zu überprüfen, ob eine PID einem gültigen Prozess entspricht? Ich erhalte eine PID von einer anderen Quelle als von os.getpid() und muss prüfen, ob auf dem Computer kein Prozess mit dieser PID vorhanden ist.

Ich brauche es, um in Unix und Windows verfügbar zu sein. Ich überprüfe auch, ob die PID NICHT verwendet wird.

92
Evan Fosmark

Das Senden des Signals 0 an eine PID löst eine OSError-Ausnahme aus, wenn die PID nicht ausgeführt wird. Andernfalls wird nichts unternommen.

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
149
mluebke

Schauen Sie sich das psutil Modul an:

psutil (Python-System und Prozessdienstprogramme) ist eine plattformübergreifende Bibliothek zum Abrufen von Informationen zu ausgeführten Prozessen und Systemauslastung (CPU, Speicher, Festplatten, Netzwerk) in Python. Es unterstützt derzeit Linux , Windows , [~ # ~] osx [~ # ~] , FreeBSD und Sun Solaris , sowohl 32-Bit als auch 64-Bit Architekturen mit Python Versionen von 2.6 bis 3.4 ( Benutzer von Python 2.4 und 2.5 können Version 2.1.3 verwenden. PyPy funktioniert auch.

Es hat eine Funktion namens pid_exists(), mit der Sie prüfen können, ob ein Prozess mit der angegebenen pid existiert.

Hier ist ein Beispiel:

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

Als Referenz:

61
moooeeeep

mluebke code ist nicht 100% korrekt; kill () kann auch EPERM auslösen (Zugriff verweigert). In diesem Fall bedeutet dies offensichtlich, dass ein Prozess vorhanden ist. Das soll funktionieren:

(bearbeitet nach Jason R. Coombs Kommentaren)

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

Dies ist unter Windows nur möglich, wenn Sie pywin32, ctypes oder ein C-Erweiterungsmodul verwenden. Wenn Sie von einer externen Bibliothek abhängig sind, können Sie psutil verwenden:

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

Die Antworten, bei denen 'Signal 0' an den Prozess gesendet wird, funktionieren nur wenn der betreffende Prozess dem Benutzer gehört, der den Test ausführt. Andernfalls erhalten Sie aufgrund von Berechtigungen ein OSError, auch wenn die pid im System vorhanden ist.

Um diese Einschränkung zu umgehen, können Sie prüfen, ob /proc/<pid> existiert:

import os

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

Dies gilt natürlich nur für Linux-basierte Systeme.

16
Omer Dagan

Suchen Sie hier nach einer Windows-spezifischen Methode, um eine vollständige Liste der ausgeführten Prozesse mit ihren IDs abzurufen. Es wäre so etwas wie

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]

Sie können dann die erhaltene PID anhand dieser Liste überprüfen. Ich habe keine Ahnung, was die Leistungskosten angehen. Sie sollten dies daher überprüfen, wenn Sie die PID-Überprüfung häufig durchführen.

Verwenden Sie für * NIx einfach mluebkes Lösung.

6

In Python 3.3+ können Sie anstelle von Fehlernummern Ausnahmenamen verwenden. 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
6
jfs

Aufbauend auf ntrrgcs habe ich die Windows-Version verbessert, damit sie den Prozess-Exit-Code überprüft und nach Berechtigungen sucht:

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
speedplane

Kombiniere Giampaolo Rodolàs Antwort für POSIX und meine für Windows Ich habe folgendes erhalten:

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
Alicia

Dies funktioniert unter Linux, wenn Sie beispielsweise überprüfen möchten, ob Banshee ausgeführt wird ... (Banshee ist ein Musik-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")
2
BARSPIN

In Windows können Sie dies folgendermaßen tun:

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

Zunächst versuchen Sie in diesem Code, ein Handle für den Prozess mit der angegebenen PID zu erhalten. Wenn das Handle gültig ist, schließen Sie das Handle für process und geben Sie True zurück. Andernfalls geben Sie False zurück. Dokumentation für OpenProcess: https://msdn.Microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

2
Andrei