Skip to content

Commit 62e2e2b

Browse files
committed
added process monitor tutorial
1 parent d8d4b74 commit 62e2e2b

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
3030
- [How to Get Hardware and System Information in Python](https://www.thepythoncode.com/article/get-hardware-system-information-python). ([code](general/sys-info))
3131
- [How to Control your Mouse in Python](https://www.thepythoncode.com/article/control-mouse-python). ([code](general/mouse-controller))
3232
- [How to Control your Keyboard in Python](https://www.thepythoncode.com/article/control-keyboard-python). ([code](general/keyboard-controller))
33+
- [How to Make a Process Monitor in Python](https://www.thepythoncode.com/article/make-process-monitor-python). ([code](general/process-monitor))
3334

general/process-monitor/README.md

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# [How to Make a Process Monitor in Python](https://www.thepythoncode.com/article/make-process-monitor-python)
2+
to run this:
3+
- `pip3 install -r requirements.txt`
4+
-
5+
```
6+
python3 process_monitor.py --help
7+
```
8+
**Output:**
9+
```
10+
usage: process_monitor.py [-h] [-c COLUMNS] [-s SORT_BY] [--descending] [-n N]
11+
12+
Process Viewer & Monitor
13+
14+
optional arguments:
15+
-h, --help show this help message and exit
16+
-c COLUMNS, --columns COLUMNS
17+
Columns to show, available are name,create_time,cores,
18+
cpu_usage,status,nice,memory_usage,read_bytes,write_by
19+
tes,n_threads,username. Default is name,cpu_usage,memo
20+
ry_usage,read_bytes,write_bytes,status,create_time,nic
21+
e,n_threads,cores.
22+
-s SORT_BY, --sort-by SORT_BY
23+
Column to sort by, default is memory_usage .
24+
--descending Whether to sort in descending order.
25+
-n N Number of processes to show, will show all if 0 is
26+
specified, default is 25 .
27+
28+
```
29+
## Examples:
30+
- Showing 10 processes sorted by create_time in ascending order:
31+
```
32+
python3 process_monitor.py --sort-by create_time -n 10
33+
```
34+
**Output:**
35+
```
36+
name cpu_usage memory_usage read_bytes write_bytes status create_time nice n_threads cores
37+
pid
38+
1 systemd 0.0 187.92MB 242.47MB 27.64MB sleeping 2019-09-09 10:56:21 0 1 4
39+
19 kworker/1:0H 0.0 0.00B 0.00B 0.00B idle 2019-09-09 10:56:21 -20 1 1
40+
17 ksoftirqd/1 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
41+
16 migration/1 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
42+
15 watchdog/1 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
43+
13 cpuhp/0 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
44+
12 watchdog/0 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
45+
11 migration/0 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
46+
14 cpuhp/1 0.0 0.00B 0.00B 0.00B sleeping 2019-09-09 10:56:21 0 1 1
47+
9 rcu_sched 0.0 0.00B 0.00B 0.00B idle 2019-09-09 10:56:21 0 1 4
48+
```
49+
- Showing 20 processes with only name, cpu_usage, memory_usage and status as columns, sorted by memory_usage in descending order:
50+
```
51+
python3 process_monitor.py --columns name,cpu_usage,memory_usage,status -n 20 --sort-by memory_usage --descending
52+
```
53+
**Output:**
54+
```
55+
name cpu_usage memory_usage status
56+
pid
57+
1312 mysqld 0.0 144.63MB sleeping
58+
915 gnome-shell 0.0 81.00MB sleeping
59+
3214 python3 0.0 58.12MB running
60+
1660 rtorrent main 0.0 35.84MB sleeping
61+
2466 rtorrent main 0.0 24.02MB sleeping
62+
3186 php 0.0 19.58MB sleeping
63+
737 Xorg 0.0 15.52MB sleeping
64+
1452 apache2 0.0 12.18MB sleeping
65+
872 teamviewerd 0.0 11.53MB sleeping
66+
974 gsd-color 0.0 8.65MB sleeping
67+
553 NetworkManager 0.0 7.71MB sleeping
68+
1045 colord 0.0 7.16MB sleeping
69+
982 gsd-keyboard 0.0 6.23MB sleeping
70+
969 gsd-clipboard 0.0 6.09MB sleeping
71+
548 ModemManager 0.0 5.68MB sleeping
72+
986 gsd-media-keys 0.0 4.94MB sleeping
73+
1001 gsd-power 0.0 4.72MB sleeping
74+
962 gsd-xsettings 0.0 4.59MB sleeping
75+
1023 gsd-wacom 0.0 4.40MB sleeping
76+
961 packagekitd 0.0 4.31MB sleeping
77+
```
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import psutil
2+
from datetime import datetime
3+
import pandas as pd
4+
5+
def get_size(bytes):
6+
"""
7+
Returns size of bytes in a nice format
8+
"""
9+
for unit in ['', 'K', 'M', 'G', 'T', 'P']:
10+
if bytes < 1024:
11+
return f"{bytes:.2f}{unit}B"
12+
bytes /= 1024
13+
14+
# the list the contain all process dictionaries
15+
processes = []
16+
for process in psutil.process_iter():
17+
# get all process info in one shot
18+
with process.oneshot():
19+
# get the process id
20+
pid = process.pid
21+
# get the name of the file executed
22+
name = process.name()
23+
# get the time the process was spawned
24+
create_time = datetime.fromtimestamp(process.create_time())
25+
try:
26+
# get the number of CPU cores that can execute this process
27+
cores = len(process.cpu_affinity())
28+
except psutil.AccessDenied:
29+
cores = 0
30+
# get the CPU usage percentage
31+
cpu_usage = process.cpu_percent()
32+
# get the status of the process (running, idle, etc.)
33+
status = process.status()
34+
try:
35+
# get the process priority (a lower value means a more prioritized process)
36+
nice = int(process.nice())
37+
except psutil.AccessDenied:
38+
nice = 0
39+
try:
40+
# get the memory usage in bytes
41+
memory_usage = process.memory_full_info().uss
42+
except psutil.AccessDenied:
43+
memory_usage = 0
44+
# total process read and written bytes
45+
io_counters = process.io_counters()
46+
read_bytes = io_counters.read_bytes
47+
write_bytes = io_counters.write_bytes
48+
# get the number of total threads spawned by this process
49+
n_threads = process.num_threads()
50+
# get the username of user spawned the process
51+
try:
52+
username = process.username()
53+
except psutil.AccessDenied:
54+
username = "N/A"
55+
56+
processes.append({
57+
'pid': pid, 'name': name, 'create_time': create_time,
58+
'cores': cores, 'cpu_usage': cpu_usage, 'status': status, 'nice': nice,
59+
'memory_usage': memory_usage, 'read_bytes': read_bytes, 'write_bytes': write_bytes,
60+
'n_threads': n_threads, 'username': username,
61+
})
62+
63+
# convert to pandas dataframe
64+
df = pd.DataFrame(processes)
65+
# set the process id as index of a process
66+
df.set_index('pid', inplace=True)
67+
if __name__ == "__main__":
68+
import argparse
69+
parser = argparse.ArgumentParser(description="Process Viewer & Monitor")
70+
parser.add_argument("-c", "--columns", help="""Columns to show,
71+
available are name,create_time,cores,cpu_usage,status,nice,memory_usage,read_bytes,write_bytes,n_threads,username.
72+
Default is name,cpu_usage,memory_usage,read_bytes,write_bytes,status,create_time,nice,n_threads,cores.""",
73+
default="name,cpu_usage,memory_usage,read_bytes,write_bytes,status,create_time,nice,n_threads,cores")
74+
parser.add_argument("-s", "--sort-by", dest="sort_by", help="Column to sort by, default is memory_usage .", default="memory_usage")
75+
parser.add_argument("--descending", action="store_true", help="Whether to sort in descending order.")
76+
parser.add_argument("-n", help="Number of processes to show, will show all if 0 is specified, default is 25 .", default=25)
77+
78+
# parse arguments
79+
args = parser.parse_args()
80+
columns = args.columns
81+
sort_by = args.sort_by
82+
descending = args.descending
83+
n = int(args.n)
84+
85+
# sort rows by the column passed as argument
86+
df.sort_values(sort_by, inplace=True, ascending=not descending)
87+
# pretty printing bytes
88+
df['memory_usage'] = df['memory_usage'].apply(get_size)
89+
df['write_bytes'] = df['write_bytes'].apply(get_size)
90+
df['read_bytes'] = df['read_bytes'].apply(get_size)
91+
# convert to proper date format
92+
df['create_time'] = df['create_time'].apply(datetime.strftime, args=("%Y-%m-%d %H:%M:%S",))
93+
# reorder and define used columns
94+
df = df[columns.split(",")]
95+
# print
96+
if n == 0:
97+
print(df.to_string())
98+
elif n > 0:
99+
print(df.head(n).to_string())
100+
101+
102+
103+
104+
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pandas
2+
psutil

0 commit comments

Comments
 (0)