developer tip

파이썬에 주어진 PID를 가진 프로세스가 있는지 확인하는 방법은 무엇입니까?

optionbox 2020. 8. 31. 07:42
반응형

파이썬에 주어진 PID를 가진 프로세스가 있는지 확인하는 방법은 무엇입니까?


PID가 유효한 프로세스에 해당하는지 확인하는 방법이 있습니까? from이 아닌 다른 소스에서 pid를 얻고 있으며 해당 pid를 가진 os.getpid()프로세스가 시스템에 존재하지 않는지 확인해야합니다.

Unix와 Windows에서 사용할 수 있어야합니다. 또한 PID가 사용되지 않는지 확인하고 있습니다.


pid에 신호 0을 보내면 pid가 실행되고 있지 않으면 OSError 예외가 발생하고 그렇지 않으면 아무것도 수행하지 않습니다.

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

psutil모듈을 살펴보십시오 .

psutil (python 시스템 및 프로세스 유틸리티)은 Python에서 실행중인 프로세스시스템 사용률 (CPU, 메모리, 디스크, 네트워크)에 대한 정보를 검색하기위한 크로스 플랫폼 라이브러리입니다 . [...] 현재 Linux , Windows , OSX , FreeBSDSun Solaris , 32 비트64 비트 아키텍처 모두를 지원하며 Python 버전 2.6에서 3.4까지 (Python 2.4 및 2.5 사용자는 2.1.3 버전을 사용할 수 있음) . PyPy도 작동하는 것으로 알려져 있습니다.

pid_exists()주어진 pid를 가진 프로세스가 존재하는지 확인하는 데 사용할 수 있는 함수 가 있습니다.

예를 들면 다음과 같습니다.

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

참고로 :


mluebke 코드가 100 % 정확하지 않습니다. kill ()은 또한 EPERM (액세스 거부)을 일으킬 수 있으며,이 경우 분명히 프로세스가 존재 함을 의미합니다. 이것은 작동합니다.

(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

pywin32, ctypes 또는 C 확장 모듈을 사용하지 않는 한 Windows에서는이 작업을 수행 할 수 없습니다. 외부 lib에 따라 괜찮다면 psutil 을 사용할 수 있습니다 .

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

프로세스에 '신호 0'을 보내는 것과 관련된 답변은 해당 프로세스가 테스트를 실행하는 사용자가 소유 한 경우에만 작동 합니다 . 그렇지 않으면 pid가 시스템에 존재하더라도 권한OSError 때문에 얻을 것 입니다.

이 제한을 우회하기 위해 /proc/<pid>존재 하는지 확인할 수 있습니다.

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.


Look here for windows-specific way of getting full list of running processes with their IDs. It would be something like

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]

You can then verify pid you get against this list. I have no idea about performance cost, so you'd better check this if you're going to do pid verification often.

For *NIx, just use mluebke's solution.


In Python 3.3+, you could use exception names instead of errno constants. 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

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

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

In Windows, you can do it in this way:

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

First of all, in this code you try to get a handle for process with pid given. If the handle is valid, then close the handle for process and return True; otherwise, you return False. Documentation for OpenProcess: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx


This will work for Linux, for example if you want to check if banshee is running... (banshee is a music 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")

I'd say use the PID for whatever purpose you're obtaining it and handle the errors gracefully. Otherwise, it's a classic race (the PID may be valid when you check it's valid, but go away an instant later)

참고URL : https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python

반응형