patternpythonMinor
Calculate CPU% by process from /proc/stat and /proc/<pid>/stat
Viewed 0 times
processpidprocstatcalculateandcpufrom
Problem
We don't have the possibility to install modules like
It uses
I added
Next - it calculates % of CPU, taken by this process:
```
#!/usr/bin/env python
import sys
import os
import time
import subprocess
if len(sys.argv) == 2:
pid = sys.argv[1]
else:
print('No PID specified. Usage: %s ' % os.path.basename(__file__))
sys.exit(1)
def proct(pid):
try:
with open(os.path.join('/proc/', pid, 'stat'), 'r') as pidfile:
proctimes = pidfile.readline()
# get utime from /proc//stat, 14 item
utime = proctimes.split(' ')[13]
# get stime from proc//stat, 15 item
stime = proctimes.split(' ')[14]
# count total process used time
proctotal = int(utime) + int(stime)
return(float(proctotal))
except IOError as e:
print('ERROR: %s' % e)
sys.exit(2)
def cput():
try:
with open('/proc/stat', 'r') as procfile:
cputimes = procfile.readline()
cputotal = 0
# count from /proc/stat: user, nice, system, idle, iowait, irc, softirq, steal, guest
for i in cputimes.split(' ')[2:]:
i = int(i)
cputotal = (cputotal + i)
return(float(cputotal))
except IOError as e:
print('ERROR: %s' % e)
sys.exit(3)
# assign start values before loop them
proctotal = proct(pid)
cputotal = cput()
try:
while True:
# for test, to compare results
proc = subprocess.Popen("top -p %s -b -n 1 | grep -w mysql | awk '{print $9}'" % pid, shell=True, stdout=
psutil on some boxes, thus I decided to write a simple script to calculate the CPU percentage by the given PID.It uses
/proc/stat to get CPU times and /proc//stat to get the process CPU usage.I added
top output here, just to compare results and to be sure it's (about) correct. But - I don't like to use external utilities in Python scripts, thus top will be removed.- OS: CentOS 6.5
- Python: 2.6.6
Next - it calculates % of CPU, taken by this process:
```
#!/usr/bin/env python
import sys
import os
import time
import subprocess
if len(sys.argv) == 2:
pid = sys.argv[1]
else:
print('No PID specified. Usage: %s ' % os.path.basename(__file__))
sys.exit(1)
def proct(pid):
try:
with open(os.path.join('/proc/', pid, 'stat'), 'r') as pidfile:
proctimes = pidfile.readline()
# get utime from /proc//stat, 14 item
utime = proctimes.split(' ')[13]
# get stime from proc//stat, 15 item
stime = proctimes.split(' ')[14]
# count total process used time
proctotal = int(utime) + int(stime)
return(float(proctotal))
except IOError as e:
print('ERROR: %s' % e)
sys.exit(2)
def cput():
try:
with open('/proc/stat', 'r') as procfile:
cputimes = procfile.readline()
cputotal = 0
# count from /proc/stat: user, nice, system, idle, iowait, irc, softirq, steal, guest
for i in cputimes.split(' ')[2:]:
i = int(i)
cputotal = (cputotal + i)
return(float(cputotal))
except IOError as e:
print('ERROR: %s' % e)
sys.exit(3)
# assign start values before loop them
proctotal = proct(pid)
cputotal = cput()
try:
while True:
# for test, to compare results
proc = subprocess.Popen("top -p %s -b -n 1 | grep -w mysql | awk '{print $9}'" % pid, shell=True, stdout=
Solution
You have code outside of functions or an
Now if you want to
I would factor out any temporary variables, e.g.
can be written:
Try not to do the same thing twice, e.g.
could be rewritten
which only calls
Consider adding docstrings to your functions, rather than the inline comments (some of which are redundant -
The main part of
can be rewritten in a functional style:
or using a generator expression:
if __name__ == "__main__" guard (which isn't ideal in itself), both above and below the various function definitions, which makes the code relatively difficult to follow. I would structure the script as follows:import os
import subprocess
import sys
import time
def proct(pid):
...
def cput():
...
def main(pid):
...
def parse_args():
...
return pid
if __name__ == "__main__":
main(parse_args())Now if you want to
import this functionality elsewhere, it's easy. Also, note that I have made the imports alphabetical, per the style guide.I would factor out any temporary variables, e.g.
proctotal = int(utime) + int(stime)
return(float(proctotal))can be written:
return float(int(utime) + int(stime))Try not to do the same thing twice, e.g.
proctimes = pidfile.readline()
utime = proctimes.split(' ')[13]
stime = proctimes.split(' ')[14]could be rewritten
proctimes = pidfile.readline().split(' ')
utime = proctime[13] # you could also call int here
stime = proctime[14]which only calls
str.split once.Consider adding docstrings to your functions, rather than the inline comments (some of which are redundant -
utime = proctimes.split(' ')[13] does not need the explanation # get utime from /proc//stat, 14 item, which just adds an extra line to read). Better function names would also help with clarity - e.g. cpu_total rather than cput.The main part of
cput:cputimes = procfile.readline()
cputotal = 0
for i in cputimes.split(' ')[2:]:
i = int(i)
cputotal = (cputotal + i)
return(float(cputotal))can be rewritten in a functional style:
return sum(map(float, procfile.readline().split(' ')[2:]))or using a generator expression:
return sum(float(s) for s in procfile.readline().split(' ')[2:])Code Snippets
import os
import subprocess
import sys
import time
def proct(pid):
...
def cput():
...
def main(pid):
...
def parse_args():
...
return pid
if __name__ == "__main__":
main(parse_args())proctotal = int(utime) + int(stime)
return(float(proctotal))return float(int(utime) + int(stime))proctimes = pidfile.readline()
utime = proctimes.split(' ')[13]
stime = proctimes.split(' ')[14]proctimes = pidfile.readline().split(' ')
utime = proctime[13] # you could also call int here
stime = proctime[14]Context
StackExchange Code Review Q#67904, answer score: 8
Revisions (0)
No revisions yet.