====== PS Package ======
===== What is it? =====
The ''ps'' package is a couple of simple classes I created to wrap a system call to ''/bin/ps'' on a *nix machine. This will parse the output of that call and give you an easy to use object that has some simple accessor functions for finding what you want in the ps output or by letting you iterate over the object itself and accessing the information for each running process.
===== The Script =====
#!/usr/bin/env python
# $Id: ps.py,v 1.5 2008/04/24 03:37:05 jay Exp $
"""
This will run a system call of '/bin/ps auxww' and parse the results and put
them in object containers for easy access to the data.
Usage:
import ps
myps = ps.PS()
for row in myps:
for col in row:
print '%s: %s' % (col , row[col])
# You can also access the row items by name
for row in myps:
print row.pid # OR...
print row['pid']
# You can search for a particular process or processes
rows = myps.getProcByName('firefox(?:-bin)?')
for row in rows:
print '%s: %s' % (row.pid , row.command)
# Get all the processes for a given user
rows = myps.getByUser('username')
for row in rows:
print '%s: %s' % (row.pid , row.command)
# Get the info for a given pid number
pidNum = open('/var/run/myproc.pid').read()
row = myps.getByPid(pidNum)
if row:
print '%s: %d' % (row.command , row.cpu_perc)
"""
import os , re
__all__ = ['PS' , 'PSRow']
class PS(object):
"""
This is the callable class. This will create an array of accessible
PSRow objects that contain all the info for current ps output.
"""
def __init__(self , psPath='/bin/ps' , psArgs='auxww'):
"""
psPath: This should be the path to the ps binary on your system.
default: /bin/ps
psArgs: These are the args to be used when calling ps. See "man ps"
for more information.
default: auxww
"""
self._rows = []
self._rawCols = []
self._psPath = psPath
self._psArgs = psArgs
self._cmd = '%s %s' % (self._psPath , self._psArgs)
self._curNum = 0
self.refresh()
def _runCommand(self):
"""
This actually runs the command and creates the array
"""
ps = os.popen(self._cmd)
self._setRawCols(ps.readline())
while True:
line = ps.readline()
if not line: break
self._rows.append(PSRow(line , self._rawCols))
ps.close()
def getRows(self):
"""
getRows() -> Returns a list of PSRow objects
"""
return self._rows
Rows = property(getRows)
def getRawCols(self):
"""
getRawCols() -> Returns a list of strings pertaining to the column
headers
"""
return self._rawCols
def _setRawCols(self , line):
for c in re.split(r'\s+' , line.strip()):
if '%' in c:
c = c.replace('%' , '') + '_perc'
self._rawCols.append(c.lower())
RawCols = property(getRawCols)
def getByPid(self , pid):
"""
Returns a PSRow object pertaining to the pid number or None if it
does not exist
"""
for row in self._rows:
if 'pid' not in row:
return None
if int(row.pid) == int(pid):
return row
return None
def getByUser(self , username):
"""
Returns a list of PSRow objects for the given username
"""
ret = []
for row in self._rows:
if 'user' not in row:
return None
if row.user == username:
ret.append(row)
return ret
def getProcByName(self , search):
"""
Returns a list of PSRow objects based on a search of the executed
commands given the PCRE string "search".
"""
ret = []
reg = re.compile(search)
for row in self._rows:
if 'command' not in row:
return None
if reg.search(row.command):
ret.append(row)
return ret
def refresh(self):
"""
Refreshes the current rows of ps output by performing another run of
ps.
"""
self._rows = []
self._rawCols = []
self._runCommand()
def __iter__(self):
"""
Makes the PS object iterable
"""
return PS._iter(self)
def _iter(self):
"""
Iterates over the rows of PSRow objects for the given instance
"""
for psr in self._rows: yield psr
class PSRow(object):
"""
This is a data structure holding all the results of a row of ps output
"""
def __init__(self , s , cols):
"""
s: The string pertaining to one row of ps output
cols: A list of the column header names
"""
self.cols = cols
self.items = {}
self._parseStr(s)
def _parseStr(self , s):
"""
Parses the ps output row string into members of this object
"""
items = re.split(r'\s+' , s.strip() , len(self.cols) - 1)
self.items = dict(zip(self.cols , items))
self.__dict__.update(self.items)
def __contains__(self , k):
"""
Returns true if the string, k, pertains to a member of this object
For example, if you wanted to know if there was a "user" column
available from the ps output you could do the following:
if 'user' in psrow:
print psrow.user
"""
return k in self.items
def __iter__(self):
"""
Makes the PSRow object iterable
"""
return PSRow._iter(self)
def _iter(self):
"""
Iterates over the keys in the PSRow object
"""
for c in self.items.keys(): yield c
def __getitem__(self , name):
"""
Allows for dictionary access to the row items:
print psrow['user']
"""
if name in self.items:
return self.items[name]
===== Usage =====
This is meant to be used purely as a library. Here is a simple example. Run ''pydoc ps'' for more information.
import ps
myps = ps.PS()
# Show each running process as a block
for row in myps:
for col, val in row.items():
print '%s: %s' % (col , val)
print
After installing, run ''pydoc ps'' for more information.
===== Install =====
Simply {{programming:python:ps.py.gz|download the script}} or copy the above into a file and put the file in your ''lib/python/site-packages'' directory. This is usually something to the effect of ''/usr/lib/python2.4/site-packages'' but it varies depending on the distro.