58

Is there any way I can get the PID by process name in 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 

For example I need to get 3110 by chrome.

martineau
  • 119,623
  • 25
  • 170
  • 301
B Faley
  • 17,120
  • 43
  • 133
  • 223

10 Answers10

77

You can get the pid of processes by name using pidof through 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]) will run the command as "pidof process_name", If the return code was non-zero it raises a CalledProcessError.

To handle multiple entries and cast to ints:

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

In [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]

Or pas the -s flag to get a single pid:

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

In [25]: get_pid("chrome")
Out[25]: 27698
Anthon
  • 69,918
  • 32
  • 186
  • 246
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • +1 seems like a perfect answer. could you explain this `return check_output(["pidof",name])` – Avinash Raj Nov 01 '14 at 11:58
  • @AvinashRaj, added an explanation, hopefully makes it a little more clear – Padraic Cunningham Nov 01 '14 at 12:03
  • 3
    Why not go through /proc entries instead of calling external tools? While common in bash scripts, it's usually not very clean to do so in python scripts. Also, what if there are multiple processes with that name? I would at least `splitlines()` the output and covert the pids to ints. – ThiefMaster Nov 01 '14 at 12:04
  • 1
    @ThiefMaster, what is not clean about using the pidof command? – Padraic Cunningham Nov 01 '14 at 12:05
  • Is it even available by default on all/most linux systems? – ThiefMaster Nov 01 '14 at 12:06
  • @ThiefMaster, as far as I know yes it is. Also I used split with map to convert to ints and handle the case *if there are multiple processes with that name*. I still don't get your problem with using the command. parsing the top output will also give multiple process id's – Padraic Cunningham Nov 01 '14 at 12:13
  • Note that check_output() is not available in Python 2.6 and older versions. – Jaime M. Feb 23 '16 at 10:17
  • 1
    @JaimeM., it is pretty trivial to implement https://gist.github.com/edufelipe/1027906 – Padraic Cunningham Feb 23 '16 at 10:24
  • @PadraicCunningham What does it mean when I get the CalledProcessError and how do it fix it to get the process Id. I am trying to make the script and run in OpenWRT. – Vraj Solanki Jun 22 '16 at 10:26
  • 7
    @AvinashRaj Since the poster of this answer has not been active, I turn to you. When I use the first snippet of code, it throws a `FileNotFoundError`. Why is this? – Voldemort's Wrath May 19 '19 at 13:11
  • @Voldemort'sWrath if you run the snippet on a device without a pidof command such as Windows, the command will not be found. This could be one reason. – Brian Hannay Apr 10 '21 at 01:16
18

You can use psutil package:

Install

pip install psutil

Usage:

import psutil

process_name = "chrome"
pid = None

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

print("Pid:", pid)
rhoitjadhav
  • 691
  • 7
  • 16
12

you can also use pgrep, in prgep you can also give pattern for match

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

you can also use awk with ps like this

ps aux | awk '/name/{print $2}'
Hackaholic
  • 19,069
  • 5
  • 54
  • 72
11

For posix (Linux, BSD, etc... only need /proc directory to be mounted) it's easier to work with os files in /proc. It's pure python, no need to call shell programs outside.

Works on python 2 and 3 ( The only difference (2to3) is the Exception tree, therefore the "except Exception", which I dislike but kept to maintain compatibility. Also could've created a custom 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)))

Sample Output (it works like pgrep):

phoemur ~/python $ ./pgrep.py bash
1487         : -bash 
1779         : /bin/bash
Mate Mrše
  • 7,997
  • 10
  • 40
  • 77
Fernando
  • 1,138
  • 1
  • 10
  • 15
9

Complete example based on the excellent @Hackaholic's answer:

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()]
Dennis Golomazov
  • 16,269
  • 5
  • 73
  • 81
6

To improve the Padraic's answer: when check_output returns a non-zero code, it raises a CalledProcessError. This happens when the process does not exists or is not running.

What I would do to catch this exception is:

#!/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")

The output:

$ python pidproc.py
list of PIDS = 31840, 31841, 41942
Alejandro Blasco
  • 1,295
  • 2
  • 20
  • 24
  • In this case, since we aren't going anything useful in try/catch, we can also use `subprocess.call` rather than `subprocess.check_output` with try/catch block. – Rajan Ponnappan Mar 02 '17 at 17:16
  • @RajanPonnappan With `subprocess.call` you only gets the return code ($?), however `subprocess.check_output` returns what you really want: the command output (in this case, the list of PIDs) – Alejandro Blasco Mar 03 '17 at 12:35
  • 1
    You are right. I got confused between the behavior of `check_call` and `check_output`. – Rajan Ponnappan Mar 03 '17 at 16:39
3

if you're using windows, you can get PID of process/app with it's image name with this code:

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

it will return you all PID of a app like firefox or chrome e.g.

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

let me know if it helped

2

If your OS is Unix base use this code:

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

Then call it and pass it a process name to get all PIDs.

>>> check_process('firefox')
['499', '621', '623', '630', '11733']
Ali Hallaji
  • 3,712
  • 2
  • 29
  • 36
1

Since Python 3.5, subprocess.run() is recommended over subprocess.check_output():

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

Also, since Python 3.7, you can use the capture_output=true parameter to capture stdout and stderr:

>>> int(subprocess.run(["pidof", "-s", "your process"], capture_output=True).stdout)
Gohu
  • 803
  • 8
  • 11
0

On Unix, you can use pyproc2 package.

Installation
pip install pyproc2
Usage
import pyproc2
chrome_pid=pyproc2.find("chrome").pid #Returns PID of first process with name "chrome"
Adam Jenča
  • 582
  • 7
  • 20