如何检查Python中是否存在具有给定pid的进程?

时间:2021-08-10 00:09:27

Is there a way to check to see if a pid corresponds to a valid process? I'm getting a pid from a different source other than from os.getpid() and I need to check to see if a process with that pid doesn't exist on the machine.

是否有方法检查pid是否对应于一个有效进程?我从不同的来源获得了一个pid,而不是来自于os.getpid(),我需要检查是否在机器上不存在这个pid的进程。

I need it to be available in Unix and Windows. I'm also checking to see if the PID is NOT in use.

我需要它在Unix和Windows中可用。我还在检查PID是否没有被使用。

11 个解决方案

#1


122  

Sending signal 0 to a pid will raise an OSError exception if the pid is not running, and do nothing otherwise.

如果不运行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

#2


49  

mluebke code is not 100% correct; kill() can also raise EPERM (access denied) in which case that obviously means a process exists. This is supposed to work:

mluebke代码不是100%正确;kill()也可以引发EPERM(访问被拒绝),在这种情况下,显然意味着一个进程存在。这应该是可行的:

(edited as per Jason R. Coombs comments)

(根据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

You can't do this on Windows unless you use pywin32, ctypes or a C extension module. If you're OK with depending from an external lib you can use psutil:

除非使用pywin32、ctype或C扩展模块,否则不能在Windows上执行此操作。如果你可以依赖外部库,你可以使用psutil:

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

#3


43  

Have a look at the psutil module:

看看psutil模块:

psutil (python system and process utilities) is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network) in Python. [...] It currently supports Linux, Windows, OSX, FreeBSD and Sun Solaris, both 32-bit and 64-bit architectures, with Python versions from 2.6 to 3.4 (users of Python 2.4 and 2.5 may use 2.1.3 version). PyPy is also known to work.

psutil (python系统和流程实用程序)是一个跨平台库,用于检索python中运行的进程和系统利用率(CPU、内存、磁盘、网络)的信息。[…它目前支持Linux、Windows、OSX、FreeBSD和Sun Solaris,都是32位和64位架构,Python版本从2.6到3.4 (Python 2.4和2.5的用户可以使用2.1.3版本)。PyPy也很有用。

It has a function called pid_exists() that you can use to check whether a process with the given pid exists.

它有一个名为pid_exists()的函数,您可以使用它来检查具有给定pid的进程是否存在。

Here's an example:

这里有一个例子:

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

For reference:

供参考:

#4


7  

The answers involving sending 'signal 0' to the process will work only if the process in question is owned by the user running the test. Otherwise you will get an OSError due to permissions, even if the pid exists in the system.

涉及向进程发送“signal 0”的答案只有在该进程属于运行测试的用户时才有效。否则,您将由于权限而获得一个OSError,即使pid存在于系统中。

In order to bypass this limitation you can check if /proc/<pid> exists:

为了绕过这个限制,您可以检查/proc/ 是否存在:

import os

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

#5


6  

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

请在这里查找特定于windows的方法,以获取具有其id的运行进程的完整列表。就像

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.

然后,您可以根据这个列表验证pid。我不知道性能成本,所以如果要经常进行pid验证,您最好检查一下。

For *NIx, just use mluebke's solution.

对于*NIx,只需使用mluebke的解决方案。

#6


6  

In Python 3.3+, you could use exception names instead of errno constants. Posix version:

在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


6  

Building upon ntrrgc's I've beefed up the windows version so it checks the process exit code and checks for permissions:

在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

#8


4  

Combining Giampaolo Rodolà's answer for POSIX and mine for Windows I got this:

结合Giampaolo Rodola对POSIX的回答和我对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

#9


2  

In Windows, you can do it in this way:

在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

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

首先,在这段代码中,您尝试使用pid获得进程的句柄。如果句柄有效,则关闭进程句柄并返回True;否则,你返回False。文档OpenProcess:https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

#10


2  

This will work for Linux, for example if you want to check if banshee is running... (banshee is a music player)

这将适用于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")

#11


-2  

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)

我想说的是,无论您获取PID的目的是什么,都要使用它,并优雅地处理错误。否则,这是一个经典的竞赛(当你检查它是否有效时,PID可能是有效的,但是在稍后的时间内就会消失)

#1


122  

Sending signal 0 to a pid will raise an OSError exception if the pid is not running, and do nothing otherwise.

如果不运行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

#2


49  

mluebke code is not 100% correct; kill() can also raise EPERM (access denied) in which case that obviously means a process exists. This is supposed to work:

mluebke代码不是100%正确;kill()也可以引发EPERM(访问被拒绝),在这种情况下,显然意味着一个进程存在。这应该是可行的:

(edited as per Jason R. Coombs comments)

(根据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

You can't do this on Windows unless you use pywin32, ctypes or a C extension module. If you're OK with depending from an external lib you can use psutil:

除非使用pywin32、ctype或C扩展模块,否则不能在Windows上执行此操作。如果你可以依赖外部库,你可以使用psutil:

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

#3


43  

Have a look at the psutil module:

看看psutil模块:

psutil (python system and process utilities) is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network) in Python. [...] It currently supports Linux, Windows, OSX, FreeBSD and Sun Solaris, both 32-bit and 64-bit architectures, with Python versions from 2.6 to 3.4 (users of Python 2.4 and 2.5 may use 2.1.3 version). PyPy is also known to work.

psutil (python系统和流程实用程序)是一个跨平台库,用于检索python中运行的进程和系统利用率(CPU、内存、磁盘、网络)的信息。[…它目前支持Linux、Windows、OSX、FreeBSD和Sun Solaris,都是32位和64位架构,Python版本从2.6到3.4 (Python 2.4和2.5的用户可以使用2.1.3版本)。PyPy也很有用。

It has a function called pid_exists() that you can use to check whether a process with the given pid exists.

它有一个名为pid_exists()的函数,您可以使用它来检查具有给定pid的进程是否存在。

Here's an example:

这里有一个例子:

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

For reference:

供参考:

#4


7  

The answers involving sending 'signal 0' to the process will work only if the process in question is owned by the user running the test. Otherwise you will get an OSError due to permissions, even if the pid exists in the system.

涉及向进程发送“signal 0”的答案只有在该进程属于运行测试的用户时才有效。否则,您将由于权限而获得一个OSError,即使pid存在于系统中。

In order to bypass this limitation you can check if /proc/<pid> exists:

为了绕过这个限制,您可以检查/proc/ 是否存在:

import os

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

#5


6  

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

请在这里查找特定于windows的方法,以获取具有其id的运行进程的完整列表。就像

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.

然后,您可以根据这个列表验证pid。我不知道性能成本,所以如果要经常进行pid验证,您最好检查一下。

For *NIx, just use mluebke's solution.

对于*NIx,只需使用mluebke的解决方案。

#6


6  

In Python 3.3+, you could use exception names instead of errno constants. Posix version:

在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


6  

Building upon ntrrgc's I've beefed up the windows version so it checks the process exit code and checks for permissions:

在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

#8


4  

Combining Giampaolo Rodolà's answer for POSIX and mine for Windows I got this:

结合Giampaolo Rodola对POSIX的回答和我对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

#9


2  

In Windows, you can do it in this way:

在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

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

首先,在这段代码中,您尝试使用pid获得进程的句柄。如果句柄有效,则关闭进程句柄并返回True;否则,你返回False。文档OpenProcess:https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx

#10


2  

This will work for Linux, for example if you want to check if banshee is running... (banshee is a music player)

这将适用于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")

#11


-2  

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)

我想说的是,无论您获取PID的目的是什么,都要使用它,并优雅地处理错误。否则,这是一个经典的竞赛(当你检查它是否有效时,PID可能是有效的,但是在稍后的时间内就会消失)