Skip to content

Commit fe60bc8

Browse files
committed
added table layout for processes, and added CPU cores' visuals
1 parent 47b37bc commit fe60bc8

File tree

4 files changed

+61
-38
lines changed

4 files changed

+61
-38
lines changed

cpu_monitor.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@ def get_cpu_usage(self):
88
cpu = psutil.cpu_percent(interval=1)
99
return self._format_usage(cpu)
1010

11+
def get_cpu_cores_usage(self):
12+
cores = psutil.cpu_percent(interval=1, percpu=True)
13+
return [self._format_core_usage(idx, core) for idx, core in enumerate(cores)]
14+
1115
def _format_usage(self, cpu):
1216
cpu_percent = cpu / 100.0
1317
cpu_visual = '#' * int(cpu_percent * self.bars) + '-' * (self.bars - int(cpu_percent * self.bars))
1418
return f"CPU: [{cpu_visual}] {cpu:.2f}%"
19+
20+
def _format_core_usage(self, core_idx, core):
21+
core_percent = core / 100.0
22+
core_visual = '#' * int(core_percent * self.bars) + '-' * (self.bars - int(core_percent * self.bars))
23+
return f"Core {core_idx}: [{core_visual}] {core:.2f}%"

main.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ def main(stdscr):
2525

2626
# Get real-time data
2727
cpu_output = cpu_monitor.get_cpu_usage()
28+
cpu_cores_output = cpu_monitor.get_cpu_cores_usage()
2829
memory_output = memory_monitor.get_memory_usage()
30+
swap_output = memory_monitor.get_swap_usage()
2931
bandwidth_output = network_monitor.get_bandwidth_usage()
3032
sys_info_output = system_info.get_system_info()
3133
processes_output = process_monitor.get_running_processes(num_processes=10)
@@ -35,36 +37,51 @@ def main(stdscr):
3537

3638
# Define color pairs
3739
curses.start_color()
38-
curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLACK)
39-
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK)
40-
curses.init_pair(3, curses.COLOR_BLUE, curses.COLOR_BLACK)
41-
curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK)
42-
curses.init_pair(5, curses.COLOR_RED, curses.COLOR_BLACK)
40+
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # CPU color
41+
curses.init_pair(2, curses.COLOR_YELLOW, curses.COLOR_BLACK) # CPU Cores color
42+
curses.init_pair(3, curses.COLOR_BLUE, curses.COLOR_BLACK) # Network color
43+
curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK) # Headers color
44+
curses.init_pair(5, curses.COLOR_RED, curses.COLOR_BLACK) # Processes color
45+
curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_BLACK) # General text color
4346

44-
# Print CPU and Memory Usage
45-
stdscr.addstr(0, 0, "CPU Usage", curses.color_pair(4))
47+
# Print CPU Usage
48+
stdscr.addstr(0, 0, "CPU Usage", curses.color_pair(4) | curses.A_BOLD)
4649
stdscr.addstr(1, 0, cpu_output[:half_width], curses.color_pair(1))
47-
stdscr.addstr(2, 0, "Memory Usage", curses.color_pair(4))
48-
stdscr.addstr(3, 0, memory_output[:half_width], curses.color_pair(2))
50+
for idx, core_output in enumerate(cpu_cores_output[:len(cpu_cores_output) // 2]):
51+
if 2 + idx < height:
52+
stdscr.addstr(2 + idx, 0, core_output[:half_width], curses.color_pair(2))
4953

50-
# Print Bandwidth Usage
51-
stdscr.addstr(0, half_width, "Network Usage", curses.color_pair(4))
52-
stdscr.addstr(1, half_width, bandwidth_output.replace('Received', '↓').replace('Sent', '↑')[:half_width], curses.color_pair(3))
54+
# Print Memory Usage and Network Usage
55+
mem_net_start = 3 + len(cpu_cores_output) // 2
56+
stdscr.addstr(mem_net_start, 0, "Memory Usage", curses.color_pair(4) | curses.A_BOLD)
57+
stdscr.addstr(mem_net_start + 1, 0, memory_output[:half_width], curses.color_pair(6))
58+
stdscr.addstr(mem_net_start + 2, 0, swap_output[:half_width], curses.color_pair(6))
59+
stdscr.addstr(mem_net_start + 4, 0, "Network Usage", curses.color_pair(4) | curses.A_BOLD)
60+
stdscr.addstr(mem_net_start + 5, 0, bandwidth_output.replace('Received', '↓').replace('Sent', '↑')[:half_width], curses.color_pair(3))
61+
62+
# Print CPU Cores in the second column
63+
stdscr.addstr(0, half_width, "CPU Cores", curses.color_pair(4) | curses.A_BOLD)
64+
for idx, core_output in enumerate(cpu_cores_output[len(cpu_cores_output) // 2:]):
65+
if 1 + idx < height:
66+
stdscr.addstr(1 + idx, half_width, core_output[:half_width], curses.color_pair(2))
5367

5468
# Print System Info
55-
stdscr.addstr(5, 0, "System Info", curses.color_pair(4))
56-
stdscr.addstr(6, 0, "-----------", curses.color_pair(4))
69+
sys_info_start = mem_net_start + 7
70+
stdscr.addstr(sys_info_start, 0, "System Info", curses.color_pair(4) | curses.A_BOLD)
5771
sys_info_lines = [line[:half_width] for line in sys_info_output.split("\n")]
5872
for idx, line in enumerate(sys_info_lines):
59-
if 7 + idx < height:
60-
stdscr.addstr(7 + idx, 0, line, curses.color_pair(4))
73+
if sys_info_start + 1 + idx < height:
74+
stdscr.addstr(sys_info_start + 1 + idx, 0, line, curses.color_pair(6))
6175

62-
# Print Running Processes
63-
stdscr.addstr(5, half_width, "Running Processes", curses.color_pair(4))
64-
stdscr.addstr(6, half_width, "-----------------", curses.color_pair(4))
76+
# Print Running Processes in a table format
77+
process_start = sys_info_start
78+
stdscr.addstr(process_start, half_width, "Running Processes", curses.color_pair(4) | curses.A_BOLD)
79+
stdscr.addstr(process_start + 1, half_width, f"{'PID':<8} {'USER':<12} {'NAME':<25} {'MEM%':<8}", curses.color_pair(6) | curses.A_BOLD)
80+
processes_output = sorted(processes_output, key=lambda p: p['memory_percent'], reverse=True)
6581
for idx, process in enumerate(processes_output):
66-
if 7 + idx < height:
67-
stdscr.addstr(7 + idx, half_width, process[:half_width], curses.color_pair(5))
82+
process_info = f"{process['pid']:<8} {process['username']:<12} {process['name']:<25} {process['memory_percent']:<8.2f}"
83+
if process_start + 2 + idx < height:
84+
stdscr.addstr(process_start + 2 + idx, half_width, process_info[:half_width], curses.color_pair(5))
6885

6986
stdscr.refresh()
7087
time.sleep(0.5) # Wait for 0.5 seconds before updating again

memory_monitor.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,12 @@ def _format_usage(self, memory):
1212
memory_percent = memory / 100.0
1313
memory_visual = '#' * int(memory_percent * self.bars) + '-' * (self.bars - int(memory_percent * self.bars))
1414
return f"Memory: [{memory_visual}] {memory:.2f}%"
15+
16+
def get_swap_usage(self):
17+
swap = psutil.swap_memory().percent
18+
return self._format_usage_swap(swap)
19+
20+
def _format_usage_swap(self, swap):
21+
swap_percent = swap / 100.0
22+
swap_visual = '#' * int(swap_percent * self.bars) + '-' * (self.bars - int(swap_percent * self.bars))
23+
return f"Swap: [{swap_visual}] {swap:.2f}%"

processes.py

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,11 @@
22

33
class ProcessMonitor:
44
def get_running_processes(self, num_processes=10):
5-
processes = psutil.process_iter(attrs=['name', 'pid', 'username'])
6-
process_info = []
7-
for process in processes:
5+
processes = []
6+
for process in psutil.process_iter(attrs=['pid', 'name', 'username', 'memory_percent']):
87
try:
9-
name = process.info['name']
10-
pid = process.info['pid']
11-
username = process.info['username']
12-
process_info.append(f"{name} (PID: {pid}, User: {username})")
8+
processes.append(process.info)
139
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
1410
continue
15-
if len(process_info) >= num_processes:
16-
break
17-
return process_info
18-
19-
# Example usage:
20-
if __name__ == "__main__":
21-
process_monitor = ProcessMonitor()
22-
processes = process_monitor.get_running_processes()
23-
for process in processes:
24-
print(process)
11+
sorted_processes = sorted(processes, key=lambda p: p['memory_percent'], reverse=True)
12+
return sorted_processes[:num_processes]

0 commit comments

Comments
 (0)