打印进程树,结合psutil

打印进程树,结合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

猜你喜欢

转载自blog.csdn.net/Lovegengxin/article/details/80497166