Как получить PID по имени процесса?

Есть ли способ получить PID по имени процесса в Python?

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND                                                                                        
 3110 meysam    20   0  971m 286m  63m S  14.0  7.9  14:24.50 chrome 

Например, мне нужно получить 3110 на chrome.


person B Faley    schedule 01.11.2014    source источник
comment
Процессов с одинаковым именем и разными PID может быть больше.   -  person Adam Jenča    schedule 01.07.2021


Ответы (10)


Вы можете получить pid процессов по имени, используя pidof через subprocess.check_output:

from subprocess import check_output
def get_pid(name):
    return check_output(["pidof",name])


In [5]: get_pid("java")
Out[5]: '23366\n'

check_output(["pidof",name]) выполнит команду как "pidof process_name", Если код возврата не равен нулю, возникнет ошибка CalledProcessError.

Чтобы обрабатывать несколько записей и приводить их к целым числам:

from subprocess import check_output
def get_pid(name):
    return map(int,check_output(["pidof",name]).split())

В [21]: get_pid("chrome")

Out[21]: 
[27698, 27678, 27665, 27649, 27540, 27530, 27517, 14884, 14719, 13849, 13708, 7713, 7310, 7291, 7217, 7208, 7204, 7189, 7180, 7175, 7166, 7151, 7138, 7127, 7117, 7114, 7107, 7095, 7091, 7087, 7083, 7073, 7065, 7056, 7048, 7028, 7011, 6997]

Или передайте флаг -s, чтобы получить один pid:

def get_pid(name):
    return int(check_output(["pidof","-s",name]))

In [25]: get_pid("chrome")
Out[25]: 27698
person Padraic Cunningham    schedule 01.11.2014
comment
+1 кажется идеальным ответом. не могли бы вы объяснить это return check_output(["pidof",name]) - person Avinash Raj; 01.11.2014
comment
@AvinashRaj, добавил объяснение, надеюсь, прояснит ситуацию - person Padraic Cunningham; 01.11.2014
comment
Почему бы не просмотреть записи /proc вместо вызова внешних инструментов? Хотя это часто встречается в сценариях bash, обычно это не очень чисто в сценариях python. Кроме того, что, если существует несколько процессов с таким именем? Я бы по крайней мере splitlines() вывел и преобразовал pids в ints. - person ThiefMaster; 01.11.2014
comment
@ThiefMaster, что не так с использованием команды pidof? - person Padraic Cunningham; 01.11.2014
comment
Доступен ли он по умолчанию во всех/большинстве Linux-систем? - person ThiefMaster; 01.11.2014
comment
@ThiefMaster, насколько я знаю, да. Также я использовал разделение с картой для преобразования в целые числа и обработки случая, если есть несколько процессов с таким именем. Я все еще не понимаю вашей проблемы с использованием команды. разбор верхнего вывода также даст несколько идентификаторов процесса - person Padraic Cunningham; 01.11.2014
comment
Обратите внимание, что функция check_output() недоступна в Python 2.6 и более ранних версиях. - person Jaime M.; 23.02.2016
comment
@PadraicCunningham Что это значит, когда я получаю CalledProcessError и как это исправить, чтобы получить идентификатор процесса. Я пытаюсь сделать скрипт и запустить его в OpenWRT. - person Vraj Solanki; 22.06.2016
comment
@AvinashRaj Поскольку постер этого ответа не был активен, я обращаюсь к вам. Когда я использую первый фрагмент кода, он выдает ошибку FileNotFoundError. Почему это? - person Voldemort's Wrath; 19.05.2019
comment
@Voldemort'sWrath, если вы запустите фрагмент на устройстве без команды pidof, таком как Windows, команда не будет найдена. Это может быть одной из причин. - person Brian Hannay; 10.04.2021

Вы можете использовать пакет psutil:

Установить

pip install psutil

Использование:

import psutil

process_name = "chrome"
pid = None

for proc in psutil.process_iter():
    if process_name in proc.name():
       pid = proc.pid

person rhoitjadhav    schedule 27.11.2019

вы также можете использовать pgrep, в prgep вы также можете указать шаблон для совпадения

import subprocess
child = subprocess.Popen(['pgrep','program_name'], stdout=subprocess.PIPE, shell=True)
result = child.communicate()[0]

вы также можете использовать awk с ps, как это

ps aux | awk '/name/{print $2}'
person Hackaholic    schedule 01.11.2014
comment
Вы можете использовать одну из вспомогательных функций в модуле подпроцесса... намного читабельнее. Кроме того, выполнение его внутри оболочки - действительно плохая идея! - person ThiefMaster; 01.11.2014
comment
да, это просто концепция, я дал ОП - person Hackaholic; 01.11.2014
comment
лучше бегать с shell=False. - person sobolevn; 11.11.2015
comment
Отличный ответ! Я написал полный пример на его основе здесь: stackoverflow.com/a/44712205/304209 - person Dennis Golomazov; 23.06.2017

Для posix (Linux, BSD и т. д. требуется только смонтировать каталог /proc) проще работать с файлами os в /proc. Это чистый python, нет необходимости вызывать программы оболочки извне.

Работает на python 2 и 3 (Единственная разница (2to3) - это дерево исключений, поэтому except Exception, которое мне не нравится, но сохранено для обеспечения совместимости. Также можно было бы создать собственное исключение.)

#!/usr/bin/env python

import os
import sys


for dirname in os.listdir('/proc'):
    if dirname == 'curproc':
        continue

    try:
        with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd:
            content = fd.read().decode().split('\x00')
    except Exception:
        continue

    for i in sys.argv[1:]:
        if i in content[0]:
            print('{0:<12} : {1}'.format(dirname, ' '.join(content)))

Пример вывода (он работает как pgrep):

phoemur ~/python $ ./pgrep.py bash
1487         : -bash 
1779         : /bin/bash
person Fernando    schedule 13.08.2015
comment
В семействе Solaris /proc является двоичным, а не текстовым. - person ; 27.11.2019

Полный пример, основанный на превосходном ответе @Hackaholic:

def get_process_id(name):
    """Return process ids found by (partial) name or regex.

    >>> get_process_id('kthreadd')
    [2]
    >>> get_process_id('watchdog')
    [10, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61]  # ymmv
    >>> get_process_id('non-existent process')
    []
    """
    child = subprocess.Popen(['pgrep', '-f', name], stdout=subprocess.PIPE, shell=False)
    response = child.communicate()[0]
    return [int(pid) for pid in response.split()]
person Dennis Golomazov    schedule 23.06.2017

Чтобы улучшить ответ Падраика: когда check_output возвращает ненулевой код, возникает ошибка CalledProcessError. Это происходит, когда процесс не существует или не запущен.

Что бы я сделал, чтобы поймать это исключение:

#!/usr/bin/python

from subprocess import check_output, CalledProcessError

def getPIDs(process):
    try:
        pidlist = map(int, check_output(["pidof", process]).split())
    except  CalledProcessError:
        pidlist = []
    print 'list of PIDs = ' + ', '.join(str(e) for e in pidlist)

if __name__ == '__main__':
    getPIDs("chrome")

Выход:

$ python pidproc.py
list of PIDS = 31840, 31841, 41942
person Alejandro Blasco    schedule 11.03.2016
comment
В этом случае, поскольку в блоке try/catch нет ничего полезного, мы также можем использовать subprocess.call вместо subprocess.check_output с блоком try/catch. - person Rajan Ponnappan; 02.03.2017
comment
@RajanPonnappan С subprocess.call вы получаете только код возврата ($?), однако subprocess.check_output возвращает то, что вам действительно нужно: вывод команды (в данном случае список PID) - person Alejandro Blasco; 03.03.2017
comment
Ты прав. Я запутался между поведением check_call и check_output. - person Rajan Ponnappan; 03.03.2017

Начиная с Python 3.5, subprocess.run() рекомендуется вместо subprocess.check_output():

>>> int(subprocess.run(["pidof", "-s", "your_process"], stdout=subprocess.PIPE).stdout)

Кроме того, начиная с Python 3.7, вы можете использовать параметр capture_output=true для захвата stdout и stderr:

>>> int(subprocess.run(["pidof", "-s", "your process"], capture_output=True).stdout)
person Gohu    schedule 18.04.2019

Если ваша ОС является базой Unix, используйте этот код:

import os
def check_process(name):
    output = []
    cmd = "ps -aef | grep -i '%s' | grep -v 'grep' | awk '{ print $2 }' > /tmp/out"
    os.system(cmd % name)
    with open('/tmp/out', 'r') as f:
        line = f.readline()
        while line:
            output.append(line.strip())
            line = f.readline()
            if line.strip():
                output.append(line.strip())

    return output

Затем вызовите его и передайте ему имя процесса, чтобы получить все PID.

>>> check_process('firefox')
['499', '621', '623', '630', '11733']
person Ali Hallaji    schedule 30.01.2019

если вы используете окна, вы можете получить PID процесса/приложения с его именем изображения с помощью этого кода:

from subprocess import Popen, PIPE

def get_pid_of_app(app_image_name):
    final_list = []
    command = Popen(['tasklist', '/FI', f'IMAGENAME eq {app_image_name}', '/fo', 'CSV'], stdout=PIPE, shell=False)
    msg = command.communicate()
    output = str(msg[0])
    if 'INFO' not in output:
        output_list = output.split(app_image_name)
        for i in range(1, len(output_list)):
            j = int(output_list[i].replace("\"", '')[1:].split(',')[0])
            if j not in final_list:
                final_list.append(j)

    return final_list

он вернет вам все PID приложения, такого как firefox или chrome, например.

>>> get_pid_of_app("firefox.exe")
[10908, 4324, 1272, 6936, 1412, 2824, 6388, 1884]

дайте мне знать, если это помогло

person Ali Alavizadeh    schedule 01.06.2021

В Unix можно использовать пакет pyproc2.

Установка
pip install pyproc2
Применение
import pyproc2
chrome_pid=pyproc2.find("chrome").pid #Returns PID of first process with name "chrome"
person Adam Jenča    schedule 01.07.2021