Как проверить, существует ли процесс с заданным pid в Python?
есть ли способ проверить, соответствует ли pid допустимому процессу? Я получаю pid из другого источника, отличного от os.getpid() и мне нужно проверить, если процесс с этим pid не существует на машине.
Мне нужно, чтобы он был доступен в Unix и Windows. Я также проверяю, чтобы увидеть, если идентификатор не используется.
11 ответов:
отправка сигнала 0 в pid вызовет исключение OSError, если pid не работает, и ничего не делать иначе.
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
код mluebke не на 100% корректен; kill() также может вызвать EPERM (доступ запрещен), и в этом случае это, очевидно, означает, что процесс существует. Это должно работать:
(отредактировано в соответствии с комментариями Джейсона Р. Кумбса)
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вы не можете сделать это в Windows, Если вы не используете pywin32, ctypes или модуль расширения C. Если вы в порядке с зависимостью от внешней библиотеки, вы можете использовать psutil:
>>> import psutil >>> psutil.pid_exists(2353) True
посмотреть
psutilмодуль:psutil (python system and process utilities) - это кроссплатформенная библиотека для получения информации о запущенных процессов и использование системы (процессор, память, диски, сеть) в Python. [...] В настоящее время он поддерживает Linux, Windows, OSX,FreeBSD и Солнце Солярис, оба 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для ссылка:
ответы, связанные с отправкой "сигнала 0" в процесс, будут работать только если данный процесс принадлежит пользователю, выполняющему тест. В противном случае вы получите
OSErrorиз-за разрешения, даже если pid существует в системе.чтобы обойти это ограничение, вы можете проверить, если :
import os def is_running(pid): if os.path.isdir('/proc/{}'.format(pid)): return True return Falseэто относится только к системам на базе linux, очевидно.
посмотреть здесь для 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.
в 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
основываясь на 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
объединение ответ Джампаоло Родолы для 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
в 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
Это будет работать для 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")
Я бы сказал, использовать PID для любой цели вы получаете его и обрабатывать ошибки изящно. В противном случае это классическая гонка (PID может быть действительным, когда вы проверяете его действительность, но уходите через мгновение)
Comments