60

Several processes with the same name are running on host. What is the cross-platform way to get PIDs of those processes by name using python or jython?

  1. I want something like pidof but in python. (I don't have pidof anyway.)
  2. I can't parse /proc because it might be unavailable (on HP-UX).
  3. I do not want to run os.popen('ps') and parse the output because I think it is ugly (field sequence may be different in different OS).
  4. Target platforms are Solaris, HP-UX, and maybe others.
Julien
  • 13,986
  • 5
  • 29
  • 53
Alex Bolotov
  • 8,781
  • 9
  • 53
  • 57

9 Answers9

82

You can use psutil (https://github.com/giampaolo/psutil), which works on Windows and UNIX:

import psutil

PROCNAME = "python.exe"

for proc in psutil.process_iter():
    if proc.name() == PROCNAME:
        print(proc)

On my machine it prints:

<psutil.Process(pid=3881, name='python.exe') at 140192133873040>

EDIT 2017-04-27 - here's a more advanced utility function which checks the name against processes' name(), cmdline() and 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(p)
    return ls
Voy
  • 5,286
  • 1
  • 49
  • 59
Giampaolo Rodolà
  • 12,488
  • 6
  • 68
  • 60
  • 1
    Unfortunately OS X does not allow you to access many attributes of a process (name, exe, cmdline), even if you only try to access those processes that are created by you. Unless you run the interpreter/script with sudo, that is. – John Sep 20 '11 at 23:40
  • 1
    Yes, that's a limitation of OSX (and it's the only platform behaving like that). There's nothing you can do about it except using sudo/setuid. – Giampaolo Rodolà Feb 03 '12 at 09:17
  • 1
    Update - this is now fixed for different methods, see: https://code.google.com/p/psutil/issues/detail?id=297 – Giampaolo Rodolà Mar 07 '13 at 00:25
  • In my environment `.name` was a method, not a property. – ThorSummoner Feb 06 '15 at 17:57
  • so how would this identify my process from among multiple python processes? – n611x007 Feb 20 '15 at 13:33
  • It shouldn't. The only way a process is uniquely identified as long as it's alive is via its PID (which can be reused after it's gone), but when you don't know the PID you might look for its name, or cmdline, or whatever. – Giampaolo Rodolà Feb 20 '15 at 15:53
  • It would be great to see psutil support for Jython. Some of it might work now, if psutil didn't rely on `sys.platform` (`'java1.8.0_45'` on my system) to determine the underlying OS; there is a [bug in reading /proc](http://bugs.jython.org/issue2358) that needs to be fixed; other parts using the C Extension API might once [Stefan's work](http://gsoc2015-jyni.blogspot.com/) is complete. – Jim Baker May 27 '15 at 21:57
  • This example needs extra boilerplate for catching `NoSuchProcess`. Without it, it's impossible to iterate through `process_iter()` without hitting a `ZombieProcess` exception. Checking `is_running()` and `status()` are not enough to avoid this exception, at least on OS X. – Nick Chammas Feb 13 '16 at 16:52
  • On my platform(Windows 7 and Python 2.7) I couldn't get any information other than pid and name... Why no CMDLINE? – dofine Apr 01 '16 at 12:50
  • Unfortunately psutil uses a method that often fails for services... even though the user would otherwise have permission to get a limited set of features. Needed to patch it to get it to play nice with restricted info and not toss PermissionError exceptions. – Erik Aronesty Apr 25 '18 at 19:15
  • How did you patch it? – Giampaolo Rodolà Apr 26 '18 at 02:31
14

There's no single cross-platform API, you'll have to check for OS. For posix based use /proc. For Windows use following code to get list of all pids with coresponding process names

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]

You can then easily filter out processes you need. For more info on available properties of Win32_Process check out Win32_Process Class

Ivan
  • 1,735
  • 1
  • 17
  • 26
  • 1
    This library doesn't come standard with Python, at least not with 2.7. Didn't check the other versions. – Zoran Pavlovic Oct 11 '12 at 09:25
  • 2
    @ZoranPavlovic yes and it is the `pywin32` package with builds http://sourceforge.net/projects/pywin32/files/pywin32/ the answer should have included this – n611x007 Feb 20 '15 at 13:36
13
import psutil

process = filter(lambda p: p.name() == "YourProcess.exe", psutil.process_iter())
for i in process:
  print i.name,i.pid

Give all pids of "YourProcess.exe"

Giampaolo Rodolà
  • 12,488
  • 6
  • 68
  • 60
baco
  • 443
  • 1
  • 5
  • 14
  • 5
    I hold no stake either way; I often hear people rant that List Comprehension is *always* the best way to filter a list because its faster. eg `process = [proc for proc in psutil.process_iter() if proc.name == "YourProcess.exe"]`. – ThorSummoner Feb 06 '15 at 17:57
5

A note on ThorSummoner's comment

process = [proc for proc in psutil.process_iter() if proc.name == "YourProcess.exe"].

I have tried it on Debian with Python 3, I think it has to be proc.name() instead of proc.name.

Community
  • 1
  • 1
pchaitat
  • 159
  • 2
  • 3
3

First, Windows (in all it's incarnations) is a non-standard OS.

Linux (and most proprietary unixen) are POSIX-compliant standard operating systems.

The C libraries reflect this dichotomy. Python reflects the C libraries.

There is no "cross-platform" way to do this. You have to hack up something with ctypes for a particular release of Windows (XP or Vista)

S.Lott
  • 384,516
  • 81
  • 508
  • 779
1

I don't think you will be able to find a purely python-based, portable solution without using /proc or command line utilities, at least not in python itself. Parsing os.system is not ugly - someone has to deal with the multiple platforms, be it you or someone else. Implementing it for the OS you are interested in should be fairly easy, honestly.

David Cournapeau
  • 78,318
  • 8
  • 63
  • 70
1

For jython, if Java 5 is used, then you can get the Java process id as following:

from java.lang.management import ManagementFactory

pid = int(ManagementFactory.getRuntimeMXBean().getName().split("@")[0])

print(pid)

This snippet will print your PID (in my case 23968)

LukeSavefrogs
  • 528
  • 6
  • 15
ccyu
  • 304
  • 2
  • 5
0

There isn't, I'm afraid. Processes are uniquely identified by pid not by name. If you really must find a pid by name, then you will have use something like you have suggested, but it won't be portable and probably will not work in all cases.

If you only have to find the pids for a certain application and you have control over this application, then I'd suggest changing this app to store its pid in files in some location where your script can find it.

ubiyubix
  • 1,036
  • 9
  • 13
0

Just use:

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

returns Process object