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


109

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

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


2
Windows는 비표준 OS입니다. 이런 종류의 물건은 휴대용이 아닙니다. 둘 다 가질 수 없다는 것을 아는 것이 우선 순위입니까? 우선 순위로 하나를 선택하고 질문을 편집하십시오.
S.Lott

26
S. 로트 @ 윈도우 표준이 아닌 OS입니다 ... 이것은 내가 SO에서 본 가장 어리석은 발언 중 하나입니다
표트르 Dobrogost

2
@Piotr Dobrogost : POSIX 표준 유닉스 및 비 POSIX 표준 Windows를 처리하는 코드를 제공 할 수 있습니까? 그렇다면 (a) 문제를 해결하고 (b) Windows가 어떻게 든 POSIX 표준을 준수 함을 명확히하는 답변을 제공하십시오.
S.Lott 2013

3
@PiotrDobrogost S.Lott의 발언은 시장 점유율보다 구현 세부 사항과 API 지원에 관한 것이 었습니다.
Roy Tinker 2014

3
Windows는 다른 대중적인 OS와 다른 OS가 서로에 대해하는 것보다 공통점이 적습니다. (웹 개발을하는 사람이라면 누구나이 제품을 악명 높은 마이크로 소프트 제품에 비유 할 수 있습니다.)하지만 @ S.Lott에 대한 응답 : 저는 Linux, OSX, BSD 등에서도 작동하지 않는 Windows 용 Python 코드를 거의 작성하지 않습니다. 솔직히 '우선 순위로 선택'이 유용한 조언이라고 생각하지 마세요. 특히 Python은 플랫폼 차이를 가능한 한 많이 추상화하기 때문입니다.
Michael Scheper 2015

답변:


162

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

3
Linux 및 OSX에서 확실히 작동하지만 Windows에 대해서는 말할 수 없습니다. 그것은 당신이 묻는 의미에서 프로세스를 죽이는 것이 아니라 기본적으로 "Are you running?"인 신호 0을 보냅니다.
mluebke

10
이것은 UNIX와 같은 신호가 없기 때문에 Windows에서는 작동하지 않습니다.
Alexander Lebedev

13
완료하려면 오류 번호가 3인지 확인해야합니다 (예외를 포착하고 첫 번째 인수를 확인). 이는 대상 프로세스가 존재하지만 신호를 보낼 권한이없는 경우에 중요합니다 (어떤 이유로 든).
haridsv 2010

8
이제 Windows에서 지원됩니다. docs.python.org/library/os.html?highlight=os.kill#os.kill
michael

15
os.kill은 Windows에서 지원되지만 프로세스를 종료 (또는 실패) 할 수 os.kill(pid, 0)있는 것과 동일 os.kill(pid, signal.CTRL_C_EVENT)합니다. 하위 프로세스에서 이것을 시도 할 때 나는 OSError위치를 얻습니다 errno==EINVAL.
Jason R. Coombs 2012

76

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)

참고로 :



pid_exists가 Windows에서 신뢰할 수없는 인스턴스가있었습니다. 죽은 PID를 사용 중이라고 잘못보고했습니다. 이는 특히 OS 업그레이드를 수행 할 때 psutil 모듈을 수시로 업데이트하라는 알림입니다.
Damon Brodie

62

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

(Jason R. Coombs 의견에 따라 편집 됨)

import errno
import os

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

haridsv는 테스트가 e.errno! = 3이어야한다고 제안합니다. 아마도 e.errno! = errno.ESRCH
Jason R. Coombs

왜? ESRCH는 "해당 프로세스 없음"을 의미합니다.
Giampaolo Rodolà 2012

2
권리. ESRCH는 "해당 프로세스 없음"을 의미하므로 errno! = ESRCH는 "해당 프로세스가 없음"또는 "프로세스가 존재하지 않음"을 의미하며 이는 함수의 이름과 매우 유사합니다. EPERM을 구체적으로 언급했지만 다른 가능한 오류 코드는 무엇을 의미합니까? ESRCH는 밀접하게 관련되어있는 반면, 검사의 의도와 느슨하게 관련된 오류 코드를 선별하는 것은 잘못된 것 같습니다.
Jason R. Coombs 2012

네가 옳아. 이제 제안한 내용을 반영하는 코드를 편집했습니다.
Giampaolo Rodolà

python3의 os.kill ()에 ProcessLookupError 발생
martinkunev

19

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

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

import os

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

이것은 분명히 리눅스 기반 시스템에만 적용됩니다.


잘못된. PermissionErrorpid가 존재 함을 의미하고 pid가 존재ProcessLookupError 하지 않으면 얻을 수 있습니다.
jfs

OSError중 하나 errno는보고를 통해 또는 더 전문 잡기를 통해 - 거부 허가로 인해 다른 사람과 차별화 할 수 PermissionError/ ProcessLookupError에서 파생 예외 OSError. 또한 프로세스가 존재하는 경우에만 권한 오류가 발생합니다. 따라서 귀하의 예제는 Linux 및 기타 Unices에서 작동하는 대체 방법 일뿐이지만 os.kill(pid, 0).
maxschlepzig

이 솔루션은 corss-platform이 아닙니다. OP는 Unix 및 Windows에서 사용할 수 있기를 원합니다. /procprocfs의 단지조차 BSD 또는 OSX에, 리눅스에 종료됩니다.
Charles

이 메서드는 / proc가 hidepid = 2로 마운트 된 경우 실패하고 다른 사용자가 소유 한 프로세스는 목록에 표시되지 않습니다.
퍼킨스

8

Python 3.3 이상에서는 errno 상수 대신 예외 이름을 사용할 수 있습니다. 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

7

ID와 함께 실행중인 프로세스의 전체 목록을 가져 오는 Windows 별 방법을 찾으 십시오 . 그것은 다음과 같을 것입니다.

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]

그런 다음이 목록에 대해 얻은 pid를 확인할 수 있습니다. 성능 비용에 대해 잘 모르기 때문에 pid 확인을 자주 수행하려면 이것을 확인하는 것이 좋습니다.

* NIx의 경우 mluebke의 솔루션을 사용하십시오.


이것은 나를 위해 잘 작동했습니다. 나는 프로세스 이름을 확인하고 싶었 기 때문에 "이름"을 "ProcessID"로 바꾸고 체크 인 목록으로 변환하여 True 또는 False를 반환했습니다.
JamesR

6

ntrrgc를 기반으로 Windows 버전을 강화하여 프로세스 종료 코드를 확인하고 권한을 확인합니다.

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

사실에 따라 msdn.microsoft.com/en-us/library/windows/desktop/... , GetExistCodeProcess요구 PROCESS_QUERY_INFORMATIONPROCESS_QUERY_LIMITED_INFORMATION액세스 권한을.
augustomen

코드가 잘못되었습니다. GetExitCodeProcess핸들과 포인터를 수신하고이 샘플에서는 ExitCodeProcess포인터 만 있어야 할 때 두 번째 매개 변수로 구조를 수신합니다 .
Fabio Zadrozny

OpenProcess 이후에는 GetLastError를 확인하는 것이 좋습니다. ERROR_ACCESS_DENIED는 프로세스가 존재 함을 의미합니다! 다음은이를 사용한 완전한 예입니다. gist.github.com/ociule/8a48d2a6b15f49258a87b5f55be29250
ociule

4

POSIX에 대한 Giampaolo Rodolà의 답변Windows에 대한 내 답변을 결합하여 다음 과 같은 결과를 얻었습니다.

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

Windows 버전은 Windows 8.1에서 작동하지 않습니다. GetExitCodeProcess액세스 권한이 있는지 확인 하고 확인해야합니다.
스피드 플레인

kernel32.OpenProcess오로지 사용하는 것만으로는 충분하지 않습니다. 으로 여기에 지적 "프로세스가 최근 종료되면, PID는 여전히 핸들있을 수 있습니다." kernel32.OpenProcess0이 아닌 값을 반환하는 경우 에도 kernel32.GetExitCodeProcess종료 코드를 추가로 확인 해야 합니다.
Meow

2

Windows에서는 다음과 같이 할 수 있습니다.

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

우선,이 코드에서 주어진 pid로 프로세스에 대한 핸들을 얻으려고합니다. 핸들이 유효하면 프로세스 핸들을 닫고 True를 반환합니다. 그렇지 않으면 False를 반환합니다. OpenProcess 문서 : https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx


2

예를 들어 banshee가 실행 중인지 확인하려면 Linux에서 작동합니다. (banshee는 음악 플레이어입니다)

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

이 방법은를 사용 os.kill(pid, 0)하거나 보는 것과 비교할 때 분명히 열등 /proc/{pid}합니다. 하나의 syscall을 실행하는 대신 코드가 자식을 포크하고 해당 자식에서 셸을 실행하고, 셸은 불필요한 미니 셸 스크립트를 해석하고, 셸은 pgrep을 실행하는 다른 자식을 포크하고 마지막으로 pgrep을 반복합니다 /proc. 귀하의 답변은 게시 된 질문에 대한 답변이 아닙니다. OP는 PID가 주어진 방법을 요청했습니다. 메서드에는 프로세스 이름이 필요합니다.
maxschlepzig

-2

어떤 목적 으로든 PID를 사용하고 오류를 정상적으로 처리한다고 말하고 싶습니다. 그렇지 않으면 고전적인 경주입니다 (PID가 유효한지 확인하면 유효 할 수 있지만 잠시 후에 사라집니다)


좀 더 구체적이어야했습니다. INVALIDITY를 확인하고 있습니다. 따라서 기본적으로 pid가 사용되지 않는지 확인할 수 있기를 원합니다.
Evan Fosmark

1
하지만 그 대답으로 무엇을 하시겠습니까? 그 지식을 얻은 직후, 무언가가 그 pid를 사용할 수 있습니다.
Damien_The_Unbeliever

@Damien_The_Unbeliever-내가 그 지식을 얻은 후 무언가를 사용하고 있다면 괜찮습니다. 경쟁 조건에 대해 당신이 말하는 것을 이해하지만 내 상황에는 적용되지 않는다고 확신 할 수 있습니다.
Evan Fosmark
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.