Кроссплатформенный способ получения PID по имени процесса в python

На хосте запущено несколько процессов с одинаковыми именами. Каков кросс-платформенный способ получения PID этих процессов по имени с использованием python или jython?

  1. Я хочу что-то вроде pidof но в питоне. (У меня нет pidof тем не мение.)
  2. Я не могу разобрать /proc потому что это может быть недоступно (в HP-UX).
  3. Я не хочу бегать os.popen('ps') и проанализировать вывод, потому что я думаю, что это некрасиво (последовательность полей может отличаться в разных ОС).
  4. Целевые платформы - 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

возвращает объект процесса

Другие вопросы по тегам