Кроссплатформенный способ получить PID по имени процесса в Python
-
23-08-2019 - |
Вопрос
На хосте запущено несколько процессов с одинаковым именем.Каков кросс-платформенный способ получить PID этих процессов по имени, используя питон или Джитон?
- Я хочу что-то вроде
pidof
но на питоне.(у меня нетpidof
в любом случае.) - я не могу разобрать
/proc
поскольку он может быть недоступен (в HP-UX). - я не хочу бежать
os.popen('ps')
и проанализировать вывод, потому что я считаю его некрасивым (последовательность полей может отличаться в разных ОС). - Целевые платформы — Solaris, HP-UX и, возможно, другие.
Решение
Вы можете использовать psutil (https://github.com/giampaolo/psutil), который работает в Windows и UNIX:
import psutil
PROCNAME = "python.exe"
for proc in psutil.process_iter():
if proc.name() == PROCNAME:
print(proc)
На моей машине печатается:
<psutil.Process(pid=3881, name='python.exe') at 140192133873040>
РЕДАКТИРОВАТЬ 27 апреля 2017 г. - вот более продвинутая служебная функция, которая проверяет имя по имени процесса(), cmdline() и exe():
import os
import psutil
def find_procs_by_name(name):
"Return a list of processes matching 'name'."
assert name, name
ls = []
for p in psutil.process_iter():
name_, exe, cmdline = "", "", []
try:
name_ = p.name()
cmdline = p.cmdline()
exe = p.exe()
except (psutil.AccessDenied, psutil.ZombieProcess):
pass
except psutil.NoSuchProcess:
continue
if name == name_ or cmdline[0] == name or os.path.basename(exe) == name:
ls.append(name)
return ls
Другие советы
Единого кроссплатформенного API не существует, вам придется проверять ОС.Для использования posix используйте /proc.Для Windows используйте следующий код, чтобы получить список всех PID с соответствующими именами процессов.
from win32com.client import GetObject
WMI = GetObject('winmgmts:')
processes = WMI.InstancesOf('Win32_Process')
process_list = [(p.Properties_("ProcessID").Value, p.Properties_("Name").Value) for p in processes]
Затем вы можете легко отфильтровать нужные вам процессы.Дополнительную информацию о доступных свойствах Win32_Process см. Класс Win32_Process
import psutil
process = filter(lambda p: p.name() == "YourProcess.exe", psutil.process_iter())
for i in process:
print i.name,i.pid
Дайте все PID "YourProcess.exe"
Во-первых, Windows (во всех своих воплощениях) — нестандартная ОС.
Linux (и большинство проприетарных Unixen) являются стандартными операционными системами, совместимыми с POSIX.
Библиотеки C отражают эту дихотомию.Python отражает библиотеки C.
Не существует «кросс-платформенного» способа сделать это.Вам нужно что-то взломать с помощью cтипы для конкретной версии Windows (XP или Vista)
Я не думаю, что вы сможете найти переносимое решение, полностью основанное на Python, без использования /proc или утилит командной строки, по крайней мере, не в самом Python.Анализ os.system не уродлив — кому-то приходится иметь дело с несколькими платформами, будь то вы или кто-то другой.Честно говоря, реализовать его для интересующей вас ОС должно быть довольно легко.
Боюсь, нет.Процессы однозначно идентифицируются по pid, а не по имени.Если вам действительно необходимо найти pid по имени, вам придется использовать что-то вроде того, что вы предложили, но оно не будет переносимым и, вероятно, не будет работать во всех случаях.
Если вам нужно найти pid-коды только для определенного приложения и вы можете контролировать это приложение, я бы предложил изменить это приложение так, чтобы его pid-код хранился в файлах в каком-то месте, где ваш скрипт сможет его найти.
Для jython, если используется Java 5, вы можете получить идентификатор процесса Java следующим образом:
из импорта java.lang.management *
pid = ManagementFactory.getRuntimeMXBean().getName()
Примечание о Комментарий ThorSummoner
process = [proc for proc in psutil.process_iter() if proc.name == "YourProcess.exe"].
Я пробовал это на Debian с Python 3, думаю, так и должно быть. proc.name()
вместо proc.name
.