打印进程树,结合psutil
# coding: utf-8
import psutil
from functools import wraps
# ===================================================================
# --- slots classes
# ===================================================================
class SlotBase(object):
def __init__(self, *args, **kwargs):
setted = set()
kwargs_ = dict(izip(self.__slots__, args))
kwargs_.update(kwargs)
for key, value in kwargs_.iteritems():
setattr(self, key, value)
setted.add(key)
for key in set(self.__slots__) - setted:
setattr(self, key, None)
class processinfo(SlotBase):
__slots__ = ('ppidinfo', 'child_pids', 'memory', 'create_time', 'cmdline',
'environ')
def default_if_catch(exception_clses, default=None):
def _default_if_catch(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except exception_clses:
return default
return wrapper
return _default_if_catch
class Process(object):
def __init__(self, pid, top_paths=None):
self.pid = pid
self.top_paths = top_paths
self.process = psutil.Process(pid=pid)
self._tree_string = ''
def cmdline(self):
try:
return self.process.cmdline()[0]
except Exception as e:
print e
return 'AccessDenied'
@default_if_catch(Exception, default=None)
def memory_info(self):
return self.process.memory_info().rss
@default_if_catch(Exception, default=None)
def environ(self):
return self.process.environ()
@default_if_catch(Exception, default=None)
def cpu_percent(self, interval=5.0):
"""cpu占比"""
return self.process.cpu_percent(interval)
def top(self):
"""找到当前进程的根进程"""
top_paths = [self.pid]
parent = self.process.parent()
if not parent:
return self
while parent and parent.pid:
top_paths.append(parent.pid)
parent = parent.parent()
return Process(top_paths[-1], top_paths)
def parse_ps(self, pid, children):
try:
cmdline = ''.join(psutil.Process(pid).cmdline()[0])
except Exception as e:
print (e)
cmdline = None
info = {pid: {'children': children,
'cmdline': cmdline, }}
return info
def tree_info(self):
if self.top_paths:
if len(self.top_paths) == 1:
return self.tree_info_helper()
children = Process(self.top_paths[0]).tree_info_helper()
if len(self.top_paths) > 1:
for i in self.top_paths[1:]:
topinfo = self.parse_ps(i, children)
children = topinfo
return topinfo
else:
return self.tree_info_helper()
def tree_info_helper(self, process=None, process_tree={}):
process = self.process if not process else process
try:
cmdline = ''.join(process.cmdline()[0])
except Exception as e:
print (e)
cmdline = None
process_tree.update({process.pid: {'children': {},
'cmdline': cmdline, }})
for p_children in process.children():
self.tree_info_helper(p_children, process_tree[process.pid]['children'])
return process_tree
def tree_str(self):
"""打印进程树,str类型"""
tree = self.tree_info()
for i in tree:
self._tree_string = 'PID:{} CMD:{}'\
.format(i, tree[i]['cmdline']) + '\n'
self._tree_helper(tree[i]['children'], '', 0)
return self._tree_string
def _tree_helper(self, tree, prefix, level):
count = len(tree)
for k, v in tree.items():
count -= 1
islastchild = 1 if not count else 0
str = '{} └── PID:{} CMD:{}' if islastchild else '{} ├── PID:{} CMD:{}'
self._tree_string += str.format(prefix, k, v['cmdline']) + '\n'
if count > 0:
self._tree_helper(v['children'], prefix + ' │ ', level + 1)
else:
self._tree_helper(v['children'], prefix + " ", level + 1)
def info(self):
"""系统进程树信息"""
childrenpids = []
for i in self.process.children():
childrenpids.append(Process(i.pid))
ppidinfo = Process(self.process.parent().pid) \
if self.process.parent() else self
info = processinfo(ppidinfo=ppidinfo,
childrenpids=childrenpids,
memory=self.memory_info(),
create_time=self.process.create_time()*1000,
cmdline=self.cmdline(),
environ=self.environ())
return info
def main():
p = Process(1423)
print p.tree_str()
print p.top().tree_str()
if __name__ == "__main__":
main()
执行结果:
puremastiff@puremastiffdeMacBook-Pro:~/Desktop/work% python tree.py
psutil.AccessDenied (pid=50899)
PID:50899 CMD:None
└── PID:50900 CMD:-zsh
├── PID:54726 CMD:ssh
├── PID:59304 CMD:python
├── PID:64617 CMD:scp
│ └── PID:64618 CMD:/usr/bin/ssh
├── PID:65834 CMD:tree
├── PID:58796 CMD:find
├── PID:50962 CMD:python
├── PID:50995 CMD:python
├── PID:57045 CMD:scp
│ └── PID:57046 CMD:/usr/bin/ssh
├── PID:54710 CMD:python
├── PID:65929 CMD:python
├── PID:51165 CMD:python
└── PID:57022 CMD:scp
└── PID:57023 CMD:/usr/bin/ssh
psutil.AccessDenied (pid=50899)
psutil.AccessDenied (pid=1)
PID:1 CMD:None
└── PID:1423 CMD:/Applications/iTerm.app/Contents/MacOS/iTerm2
└── PID:50898 CMD:/Applications/iTerm.app/Contents/MacOS/iTerm2
└── PID:50899 CMD:None
└── PID:50900 CMD:-zsh
├── PID:54726 CMD:ssh
├── PID:59304 CMD:python
├── PID:64617 CMD:scp
│ └── PID:64618 CMD:/usr/bin/ssh
├── PID:65834 CMD:tree
├── PID:58796 CMD:find
├── PID:50962 CMD:python
├── PID:50995 CMD:python
├── PID:57045 CMD:scp
│ └── PID:57046 CMD:/usr/bin/ssh
├── PID:54710 CMD:python
├── PID:65929 CMD:python
├── PID:51165 CMD:python
└── PID:57022 CMD:scp
└── PID:57023 CMD:/usr/bin/ssh