Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4ce02df

Browse files
committed
add network usage monitor tutorial
1 parent16872c4 commit4ce02df

File tree

6 files changed

+242
-0
lines changed

6 files changed

+242
-0
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
109109
-[How to Convert Pandas Dataframes to HTML Tables in Python](https://www.thepythoncode.com/article/convert-pandas-dataframe-to-html-table-python). ([code](general/dataframe-to-html))
110110
-[How to Make a Simple Math Quiz Game in Python](https://www.thepythoncode.com/article/make-a-simple-math-quiz-game-in-python). ([code](general/simple-math-game))
111111
-[How to Make a Button using PyGame in Python](https://www.thepythoncode.com/article/make-a-button-using-pygame-in-python). ([code](general/button-in-pygame))
112+
-[How to Make a Network Usage Monitor in Python](https://www.thepythoncode.com/article/make-a-network-usage-monitor-in-python). ([code](general/network-usage))
112113

113114

114115

‎general/network-usage/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#[How to Make a Network Usage Monitor in Python](https://www.thepythoncode.com/article/make-a-network-usage-monitor-in-python)
2+
To run the scripts:
3+
-`pip3 install -r requirements.txt`
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
importpsutil
2+
importtime
3+
4+
UPDATE_DELAY=1# in seconds
5+
6+
defget_size(bytes):
7+
"""
8+
Returns size of bytes in a nice format
9+
"""
10+
forunitin ['','K','M','G','T','P']:
11+
ifbytes<1024:
12+
returnf"{bytes:.2f}{unit}B"
13+
bytes/=1024
14+
15+
# get the network I/O stats from psutil
16+
io=psutil.net_io_counters()
17+
# extract the total bytes sent and received
18+
bytes_sent,bytes_recv=io.bytes_sent,io.bytes_recv
19+
20+
whileTrue:
21+
# sleep for `UPDATE_DELAY` seconds
22+
time.sleep(UPDATE_DELAY)
23+
# get the stats again
24+
io_2=psutil.net_io_counters()
25+
# new - old stats gets us the speed
26+
us,ds=io_2.bytes_sent-bytes_sent,io_2.bytes_recv-bytes_recv
27+
# print the total download/upload along with current speeds
28+
print(f"Upload:{get_size(io_2.bytes_sent)} "
29+
f", Download:{get_size(io_2.bytes_recv)} "
30+
f", Upload Speed:{get_size(us/UPDATE_DELAY)}/s "
31+
f", Download Speed:{get_size(ds/UPDATE_DELAY)}/s ",end="\r")
32+
# update the bytes_sent and bytes_recv for next iteration
33+
bytes_sent,bytes_recv=io_2.bytes_sent,io_2.bytes_recv
34+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
importpsutil
2+
importtime
3+
importos
4+
importpandasaspd
5+
6+
UPDATE_DELAY=1# in seconds
7+
8+
defget_size(bytes):
9+
"""
10+
Returns size of bytes in a nice format
11+
"""
12+
forunitin ['','K','M','G','T','P']:
13+
ifbytes<1024:
14+
returnf"{bytes:.2f}{unit}B"
15+
bytes/=1024
16+
17+
# get the network I/O stats from psutil on each network interface
18+
# by setting `pernic` to `True`
19+
io=psutil.net_io_counters(pernic=True)
20+
21+
whileTrue:
22+
# sleep for `UPDATE_DELAY` seconds
23+
time.sleep(UPDATE_DELAY)
24+
# get the network I/O stats again per interface
25+
io_2=psutil.net_io_counters(pernic=True)
26+
# initialize the data to gather (a list of dicts)
27+
data= []
28+
foriface,iface_ioinio.items():
29+
# new - old stats gets us the speed
30+
upload_speed,download_speed=io_2[iface].bytes_sent-iface_io.bytes_sent,io_2[iface].bytes_recv-iface_io.bytes_recv
31+
data.append({
32+
"iface":iface,"Download":get_size(io_2[iface].bytes_recv),
33+
"Upload":get_size(io_2[iface].bytes_sent),
34+
"Upload Speed":f"{get_size(upload_speed/UPDATE_DELAY)}/s",
35+
"Download Speed":f"{get_size(download_speed/UPDATE_DELAY)}/s",
36+
})
37+
# update the I/O stats for the next iteration
38+
io=io_2
39+
# construct a Pandas DataFrame to print stats in a cool tabular style
40+
df=pd.DataFrame(data)
41+
# sort values per column, feel free to change the column
42+
df.sort_values("Download",inplace=True,ascending=False)
43+
# clear the screen based on your OS
44+
os.system("cls")if"nt"inos.nameelseos.system("clear")
45+
# print the stats
46+
print(df.to_string())
47+
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
fromscapy.allimport*
2+
importpsutil
3+
fromcollectionsimportdefaultdict
4+
importos
5+
fromthreadingimportThread
6+
importpandasaspd
7+
8+
# get the all network adapter's MAC addresses
9+
all_macs= {iface.macforifaceinifaces.values()}
10+
# A dictionary to map each connection to its correponding process ID (PID)
11+
connection2pid= {}
12+
# A dictionary to map each process ID (PID) to total Upload (0) and Download (1) traffic
13+
pid2traffic=defaultdict(lambda: [0,0])
14+
# the global Pandas DataFrame that's used to track previous traffic stats
15+
global_df=None
16+
# global boolean for status of the program
17+
is_program_running=True
18+
19+
defget_size(bytes):
20+
"""
21+
Returns size of bytes in a nice format
22+
"""
23+
forunitin ['','K','M','G','T','P']:
24+
ifbytes<1024:
25+
returnf"{bytes:.2f}{unit}B"
26+
bytes/=1024
27+
28+
29+
defprocess_packet(packet):
30+
globalpid2traffic
31+
try:
32+
# get the packet source & destination IP addresses and ports
33+
packet_connection= (packet.sport,packet.dport)
34+
except (AttributeError,IndexError):
35+
# sometimes the packet does not have TCP/UDP layers, we just ignore these packets
36+
pass
37+
else:
38+
# get the PID responsible for this connection from our `connection2pid` global dictionary
39+
packet_pid=connection2pid.get(packet_connection)
40+
ifpacket_pid:
41+
ifpacket.srcinall_macs:
42+
# the source MAC address of the packet is our MAC address
43+
# so it's an outgoing packet, meaning it's upload
44+
pid2traffic[packet_pid][0]+=len(packet)
45+
else:
46+
# incoming packet, download
47+
pid2traffic[packet_pid][1]+=len(packet)
48+
49+
50+
defget_connections():
51+
"""A function that keeps listening for connections on this machine
52+
and adds them to `connection2pid` global variable"""
53+
globalconnection2pid
54+
whileis_program_running:
55+
# using psutil, we can grab each connection's source and destination ports
56+
# and their process ID
57+
forcinpsutil.net_connections():
58+
ifc.laddrandc.raddrandc.pid:
59+
# if local address, remote address and PID are in the connection
60+
# add them to our global dictionary
61+
connection2pid[(c.laddr.port,c.raddr.port)]=c.pid
62+
connection2pid[(c.raddr.port,c.laddr.port)]=c.pid
63+
# sleep for a second, feel free to adjust this
64+
time.sleep(1)
65+
66+
67+
defprint_pid2traffic():
68+
globalglobal_df
69+
# initialize the list of processes
70+
processes= []
71+
forpid,trafficinpid2traffic.items():
72+
# `pid` is an integer that represents the process ID
73+
# `traffic` is a list of two values: total Upload and Download size in bytes
74+
try:
75+
# get the process object from psutil
76+
p=psutil.Process(pid)
77+
exceptpsutil.NoSuchProcess:
78+
# if process is not found, simply continue to the next PID for now
79+
continue
80+
# get the name of the process, such as chrome.exe, etc.
81+
name=p.name()
82+
# get the time the process was spawned
83+
try:
84+
create_time=datetime.fromtimestamp(p.create_time())
85+
exceptOSError:
86+
# system processes, using boot time instead
87+
create_time=datetime.fromtimestamp(psutil.boot_time())
88+
# construct our dictionary that stores process info
89+
process= {
90+
"pid":pid,"name":name,"create_time":create_time,"Upload":traffic[0],
91+
"Download":traffic[1],
92+
}
93+
try:
94+
# calculate the upload and download speeds by simply subtracting the old stats from the new stats
95+
process["Upload Speed"]=traffic[0]-global_df.at[pid,"Upload"]
96+
process["Download Speed"]=traffic[1]-global_df.at[pid,"Download"]
97+
except (KeyError,AttributeError):
98+
# If it's the first time running this function, then the speed is the current traffic
99+
# You can think of it as if old traffic is 0
100+
process["Upload Speed"]=traffic[0]
101+
process["Download Speed"]=traffic[1]
102+
# append the process to our processes list
103+
processes.append(process)
104+
# construct our Pandas DataFrame
105+
df=pd.DataFrame(processes)
106+
try:
107+
# set the PID as the index of the dataframe
108+
df=df.set_index("pid")
109+
# sort by column, feel free to edit this column
110+
df.sort_values("Download",inplace=True,ascending=False)
111+
exceptKeyErrorase:
112+
# when dataframe is empty
113+
pass
114+
# make another copy of the dataframe just for fancy printing
115+
printing_df=df.copy()
116+
try:
117+
# apply the function get_size to scale the stats like '532.6KB/s', etc.
118+
printing_df["Download"]=printing_df["Download"].apply(get_size)
119+
printing_df["Upload"]=printing_df["Upload"].apply(get_size)
120+
printing_df["Download Speed"]=printing_df["Download Speed"].apply(get_size).apply(lambdas:f"{s}/s")
121+
printing_df["Upload Speed"]=printing_df["Upload Speed"].apply(get_size).apply(lambdas:f"{s}/s")
122+
exceptKeyErrorase:
123+
# when dataframe is empty again
124+
pass
125+
# clear the screen based on your OS
126+
os.system("cls")if"nt"inos.nameelseos.system("clear")
127+
# print our dataframe
128+
print(printing_df.to_string())
129+
# update the global df to our dataframe
130+
global_df=df
131+
132+
133+
defprint_stats():
134+
"""Simple function that keeps printing the stats"""
135+
whileis_program_running:
136+
time.sleep(1)
137+
print_pid2traffic()
138+
139+
140+
141+
if__name__=="__main__":
142+
# start the printing thread
143+
printing_thread=Thread(target=print_stats)
144+
printing_thread.start()
145+
# start the get_connections() function to update the current connections of this machine
146+
connections_thread=Thread(target=get_connections)
147+
connections_thread.start()
148+
# start sniffing
149+
print("Started sniffing")
150+
sniff(prn=process_packet,store=False)
151+
# setting the global variable to False to exit the program
152+
is_program_running=False
153+
154+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
psutil
2+
scapy
3+
pandas

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp