Кроссплатформенный способ получения PID по имени процесса в python
На хосте запущено несколько процессов с одинаковыми именами. Каков кросс-платформенный способ получения PID этих процессов по имени с использованием python или jython?
- Я хочу что-то вроде
pidof
но в питоне. (У меня нетpidof
тем не мение.) - Я не могу разобрать
/proc
потому что это может быть недоступно (в HP-UX). - Я не хочу бегать
os.popen('ps')
и проанализировать вывод, потому что я думаю, что это некрасиво (последовательность полей может отличаться в разных ОС). - Целевые платформы - Solaris, HP-UX и, возможно, другие.
9 ответов
Вы можете использовать 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>
РЕДАКТИРОВАТЬ 2017-04-27 - вот более продвинутая служебная функция, которая проверяет имя по именам процессов name (), 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 используйте следующий код, чтобы получить список всех pids с соответствующими именами процессов
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
Дайте все пиды "YourProcess.exe"
Примечание к комментарию ThorSummoner
process = [proc for proc in psutil.process_iter() if proc.name == "YourProcess.exe"].
Я пробовал это на Debian с Python 3, я думаю, что это должно быть proc.name()
вместо proc.name
,
Во-первых, Windows (во всех ее воплощениях) - это нестандартная ОС.
Linux (и большинство проприетарных unixen) являются стандартными операционными системами, совместимыми с POSIX.
Библиотеки C отражают эту дихотомию. Python отражает библиотеки C.
Не существует кроссплатформенного способа сделать это. Вы должны что-то взломать с помощью ctypes для определенного выпуска Windows (XP или Vista)
Я не думаю, что вы сможете найти чисто переносимое решение на основе Python без использования / proc или утилит командной строки, по крайней мере, не в самом Python. Разбор os.system не безобразен - кто-то должен иметь дело с несколькими платформами, будь то вы или кто-то еще. Реализация его для интересующей ОС должна быть довольно простой, если честно.
Боюсь, что нет. Процессы однозначно идентифицируются по pid, а не по имени. Если вам действительно нужно найти pid по имени, вам придется использовать что-то, как вы предложили, но оно не будет переносимым и, вероятно, не будет работать во всех случаях.
Если вам нужно только найти pids для определенного приложения и вы можете контролировать это приложение, то я бы предложил изменить это приложение, чтобы сохранить его pid в файлах в каком-то месте, где ваш скрипт может его найти.
Для jython, если используется Java 5, вы можете получить идентификатор процесса Java следующим образом:
из java.lang.management import *
pid = ManagementFactory.getRuntimeMXBean (). getName ()
Просто используйте:
def get_process_by_name(name):
import re, psutil
ls = list()
for p in psutil.process_iter():
if hasattr(p, 'name'):
if re.match(".*" + name + ".*", p.name()):
ls.append(p)
return ls