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

Eva*_*ark 96 python pid process

有没有办法检查pid是否对应一个有效的进程?我从不同的来源获得了一个pidos.getpid(),我需要检查是否在该机器上不存在具有该pid的进程.

我需要它在Unix和Windows中可用.我还在检查PID是否未被使用.

mlu*_*bke 153

如果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
Run Code Online (Sandbox Code Playgroud)

  • Windows上支持os.kill,但是`os.kill(pid,0)`与`os.kill(pid,signal.CTRL_C_EVENT)`相同,可能会终止进程(或失败).当我在子进程上尝试这个时,我得到一个`OSError`,其中`errno == EINVAL`. (14认同)
  • 要完成,您还应检查错误号以确保它是3(捕获异常并检查第一个arg).如果目标进程存在但您没有发送信号的权限(无论出于何种原因),这一点很重要. (12认同)
  • 这肯定不适用于Windows,因为没有类似UNIX的信号. (9认同)
  • 现在由Windows支持.http://docs.python.org/library/os.html?highlight=os.kill#os.kill (8认同)
  • 确实在linux和OSX中工作,我不能代表Windows.它不会在你要求的意义上杀死进程,它会发送信号0,这基本上是"你在运行吗?". (3认同)
  • 此代码不正确'因为它不考虑EPERM错误,对于实际存在的PID返回False.这是正确的答案:http://stackoverflow.com/a/6940314/376587 (3认同)
  • 重要提示 - 仅当相关进程由运行 check_pid() 的用户拥有时才有效 (2认同)

moo*_*eep 67

看看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
Run Code Online (Sandbox Code Playgroud)

以供参考:

  • 这是[如何`psutil`在POSIX上实现`pid_exists()`(https://github.com/giampaolo/psutil/blob/5ba055a8e514698058589d3b615d408767a6e330/psutil/_psposix.py#L28-L53).与[@GiampaoloRodolà的回答("psutil`的作者)"比较](/sf/answers/485822011/) (5认同)

Gia*_*olà 58

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
Run Code Online (Sandbox Code Playgroud)

除非使用pywin32,ctypes或C扩展模块,否则不能在Windows上执行此操作.如果您可以使用外部库,则可以使用psutil:

>>> import psutil
>>> psutil.pid_exists(2353)
True
Run Code Online (Sandbox Code Playgroud)

  • 对.由于ESRCH意味着"没有这样的过程",所以errno!= ESRCH意味着"不是没有这样的过程"或"过程存在",这与函数的名称非常相似.你特别提到了EPERM,但是其他可能的错误代码意味着什么呢?挑出与检查意图松散相关的错误代码似乎是不正确的,而ESRCH似乎密切相关. (2认同)

Ome*_*gan 17

只有当运行测试的用户拥有相关进程时,涉及向进程发送"信号0"的答案才有效.否则,你会得到一个OSError权限,即使PID系统中存在.

为了绕过此限制,您可以检查是否/proc/<pid>存在:

import os

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

这显然只适用于基于Linux的系统.


Ale*_*dev 6

这里来获取利用其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]
Run Code Online (Sandbox Code Playgroud)

然后,您可以验证此列表中的pid.我不知道性能成本,所以如果你经常要进行pid验证,你最好检查一下.

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


jfs*_*jfs 6

在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
Run Code Online (Sandbox Code Playgroud)


spe*_*ane 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
Run Code Online (Sandbox Code Playgroud)