Python Forum
Getting wanted data from the 'top' command (Linux)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Getting wanted data from the 'top' command (Linux)
#1
This script gets system data from Linux top command: load averages, number of users, and top processes' PID, USER, CPU%, and Command Path. url is also here.

#! /usr/bin/python3
from os import popen
import pprint


class Top:
    def __init__(self):
        self.general_sys_info = {
            'number_of_users': '',
            'load_averages': []
        }
        self.process = {
            'pid': '',
            'user': '',
            'cpu_percentage': '',
            'command_path': ''
        }

    def __start_process(self):
        for line in popen('top -n 1 -bc | head -15'):
            if len(line.split()) != 0:
                yield line.split()

    def run_top(self):
        first_elements = ['Tasks:', '%Cpu(s):', 'KiB', 'PID']
        for line_list in self.__start_process():
            if line_list[0] not in first_elements:
                if line_list[0] != 'top':
                    self.process['pid'] = line_list[0]
                    self.process['user'] = line_list[1]
                    self.process['cpu_percentage'] = line_list[8]
                    self.process['command_path'] = ' '.join(line_list[11:])
                    yield self.process
                else:
                    self.general_sys_info['number_of_users'] = line_list[5]
                    self.general_sys_info['load_averages'] = line_list[9:12]
                    yield self.general_sys_info


if __name__ == "__main__":
    pp = pprint.PrettyPrinter(indent=4)
    for system_info in Top().run_top():
        pp.pprint(system_info)
        print('\n')

I am kinda hoping someone might chime in...

In the client of the script... is there a better way to print the key/value pairs from a generator object?
I tried the usual .items() method and the iter() keyword but didn't work:

for k,v in Top().run_top().items():
    print(k)
    print(v)
and...

for k,v in iter(Top().run_top().items()):
    print(k)
    print(v)
Not much luck though
Reply
#2
(Nov-08-2018, 09:56 PM)rootVIII Wrote: is there a better way to print the key/value pairs from a generator object?
You can try
from itertools import chain
for k, v in chain.from_iterable(info.items() for info in Top().run_top()):
    print(k)
    print(v)
Reply
#3
Ah that's perfect! Thanks

Thanks again... Here's what I ended up using:

    for k, v in enumerate(chain.from_iterable(info.items() for info in Top().run_top())):
        if k < 2 or 'command_path' in v:
            print("%s: %s\n" % (v[0],  v[1]))
        else:
            print("%s: %s" % (v[0], v[1]))
Reply
#4
forgot to post the completed version:

#! /usr/bin/python3
# get system data from top: load averages, number of users,
# and top processes' PID, USER, CPU%, and Command Path
from os import popen
from itertools import chain


class Top:
    def __init__(self):
        self.general_sys_info = {
            'number_of_users': '',
            'load_averages': []
        }
        self.process = {
            'pid': '',
            'user': '',
            'cpu_percentage': '',
            'command_path': ''
        }

    def __start_process(self):
        for line in popen('top -n 1 -bc | head -15'):
            if len(line.split()) != 0:
                yield line.split()

    def run_top(self):
        first_elements = ['Tasks:', '%Cpu(s):', 'KiB', 'PID']
        for line_list in self.__start_process():
            if line_list[0] not in first_elements:
                if line_list[0] != 'top':
                    self.process['pid'] = line_list[0]
                    self.process['user'] = line_list[1]
                    self.process['cpu_percentage'] = line_list[8]
                    self.process['command_path'] = ' '.join(line_list[11:])
                    yield self.process
                else:
                    self.general_sys_info['number_of_users'] = line_list[5]
                    self.general_sys_info['load_averages'] = line_list[9:12]
                    yield self.general_sys_info


if __name__ == "__main__":
    for k, v in enumerate(chain.from_iterable(i.items() for i in Top().run_top())):
        if k < 2 or 'command_path' in v:
            print("%s: %s\n" % (v[0],  v[1]))
        else:
            print("%s: %s" % (v[0], v[1]))
Reply
#5
Good one!

How about reading the data straight from /proc?
I was tried to research where are all the data I want to get from /proc but I didn't manage to learn enough. Perhaps I have to dig deeper.

Right now I am just reading the cpu cores temperature.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#6
wavic Wrote:Right now I am just reading the cpu cores temperature.
Aren't you reinventing the wheel? We already have psutil.sensors_temperatures()
Reply
#7
(Nov-16-2018, 07:50 AM)Gribouillis Wrote:
wavic Wrote:Right now I am just reading the cpu cores temperature.
Aren't you reinventing the wheel? We already have psutil.sensors_temperatures()

Not really. I know this module and I use it for a few scripts but I want to know also, where is the source of the data I need.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#8
It's cool to build own tools. Additionally you can explore linux and learn how to handle pathlib for example.

def lspids():
    pids = []
    for path in pathlib.Path('/proc').iterdir():
        if path.name.isdigit():
            pids.append(int(path.name))
    return pids
Now you can explore the subdirectories of pids in /proc.
You should look here: http://tldp.org/LDP/Linux-Filesystem-Hie.../proc.html
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Command output to pdf (linux) Gribouillis 0 4,970 Mar-05-2021, 07:35 PM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020