CPU, RAM and disk monitoring using python


12 posts
by PhJulien » Mon Nov 05, 2012 10:02 pm
Hi everybody,

I am currently working on an application to use my RPi to monitor what is happening in my flat (temperature, ...) but I also want to use this application to monitor how fine my RPi is going.

As it might be of interest for some of you I decided to share some code to monitor the CPU, RAM and disk of the RPi (I have a model B, 512 Mb, Raspbian and use python 2.7 + pygame for the interface).

First the functions that can allow you to retrieve CPU information (temperature + usage), RAM info (total, usage) and disk usage (total, usage). The comments generally explain quite well the functions that actually rely on Unix commands launched from Python.

Code: Select all
import os

# Return CPU temperature as a character string                                     
def getCPUtemperature():
    res = os.popen('vcgencmd measure_temp').readline()
    return(res.replace("temp=","").replace("'C\n",""))

# Return RAM information (unit=kb) in a list                                       
# Index 0: total RAM                                                               
# Index 1: used RAM                                                                 
# Index 2: free RAM                                                                 
def getRAMinfo():
    p = os.popen('free')
    i = 0
    while 1:
        i = i + 1
        line = p.readline()
        if i==2:
            return(line.split()[1:4])

# Return % of CPU used by user as a character string                               
def getCPUuse():
    return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip(\
)))

# Return information about disk space as a list (unit included)                     
# Index 0: total disk space                                                         
# Index 1: used disk space                                                         
# Index 2: remaining disk space                                                     
# Index 3: percentage of disk used                                                 
def getDiskSpace():
    p = os.popen("df -h /")
    i = 0
    while 1:
        i = i +1
        line = p.readline()
        if i==2:
            return(line.split()[1:5])


If you want to call the function here are some examples:

Code: Select all
# CPU informatiom
CPU_temp = getCPUtemperature()
CPU_usage = getCPUuse()

# RAM information
# Output is in kb, here I convert it in Mb for readability
RAM_stats = getRAMinfo()
RAM_total = round(int(RAM_stats[0]) / 1000,1)
RAM_used = round(int(RAM_stats[1]) / 1000,1)
RAM_free = round(int(RAM_stats[2]) / 1000,1)

# Disk information
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_free = DISK_stats[1]
DISK_perc = DISK_stats[3]



I used these chunks of codes for my interface and, so far, it works nicely and gives this kind of results: see image. The design still sucks (icons are not very explicit) but I will work on this later. :)

If you have any questions or want to share your tips to monitor your RPi activity using Python feel free to use this topic. By the way, the code presented here is of course free to be used. I do not guarantee it will work on every RPi but I hope so. =)

Final comment: I didn't know where to post this topic. Please move it if you think it is better suited in an other forum.

Philippe.
Not a native speaker. Sorry for my english. =)
Posts: 11
Joined: Wed Oct 31, 2012 9:41 am
Location: Lausanne, Switzerland
by BlackJack » Tue Nov 06, 2012 7:43 am
@PhJulien: You are mostly reinventing the `psutil` module which can be installed with ``sudo apt-get python-psutil``. It is cross platform, so code using it also works on Windows, MacOSX, and FreeBSD. That module can even examine single processes for CPU and memory usage, asked for subprocesses and threads, open files, network connections, I/O amount, …

This leaves the CPU temperature as the only Raspi specific value. The `subprocess` module is meant to replace all the other ways to call external programs.

Example:
Code: Select all
#!/usr/bin/env python
from __future__ import division
from subprocess import PIPE, Popen
import psutil


def get_cpu_temperature():
    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE)
    output, _error = process.communicate()
    return float(output[output.index('=') + 1:output.rindex("'")])


def main():
    cpu_temperature = get_cpu_temperature()
    cpu_usage = psutil.cpu_percent()
   
    ram = psutil.phymem_usage()
    ram_total = ram.total / 2**20       # MiB.
    ram_used = ram.used / 2**20
    ram_free = ram.free / 2**20
    ram_percent_used = ram.percent
   
    disk = psutil.disk_usage('/')
    disk_total = disk.total / 2**30     # GiB.
    disk_used = disk.used / 2**30
    disk_free = disk.free / 2**30
    disk_percent_used = disk.percent
    #
    # Print top five processes in terms of virtual memory usage.
    #
    processes = sorted(
        ((p.get_memory_info().vms, p) for p in psutil.process_iter()),
        reverse=True
    )
    for virtual_memory, process in processes[:5]:
        print virtual_memory // 2**20, process.pid, process.name


if __name__ == '__main__':
    main()
Code: Select all
while not self.asleep():
    sheep += 1
Posts: 288
Joined: Sat Aug 04, 2012 8:28 am
by PhJulien » Tue Nov 06, 2012 8:42 am
Hi,

thanks for the pointer, I didn't know this library. I looked for something similar but, surprisingly, did not come across this one. Maybe because at the beginning I was mostly looking for how to monitor CPU temperature, which is specific to the RPi...

Well, thanks again. =)

Philippe.
Not a native speaker. Sorry for my english. =)
Posts: 11
Joined: Wed Oct 31, 2012 9:41 am
Location: Lausanne, Switzerland
by ialbizu » Tue Jan 22, 2013 9:31 am
Hi.

I have problems to import psutil
I Installed psutil with
Code: Select all
sudo apt-get install python-pip python-dev
sudo pip install psutil

later I installed
Code: Select all
sudo apt-get install python-psutil

I can see the module psutil with "pydoc modules" but in my script show an error " ImportError: No module named psutil"

Do you know the problem.

Thanks
Posts: 36
Joined: Mon Jan 14, 2013 9:23 am
Location: Spain, Zaragoza
by timhoffman » Tue Jan 22, 2013 11:36 am
Hi

My guess is the pip install of ps-utils didn't work, that would install from PyPI which would require compilation of OS/platform specific code.

I just tried install directly with apt-get install python-psutils and it works fine.

I would suggest you can confirm this by running python with -v option (this traces the imports)
Chances are the import is in fact failing because some 'c' binary can't be imported.

You best bet is to probably get rid of the install of ps-utils and re-install using apt-get.

Cheers

Tim
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm
by ialbizu » Tue Jan 22, 2013 2:31 pm
I download psutil from http://code.google.com/p/psutil/
I intalled it.
I execute a script

Code: Select all
#!/usr/bin/python
import psutil
print("hola")


And appear the same error." ImportError: No module named psutil"

I try to executo python with -v, and this is the result

Code: Select all
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# /usr/lib/python2.7/site.pyc matches /usr/lib/python2.7/site.py
import site # precompiled from /usr/lib/python2.7/site.pyc
# /usr/lib/python2.7/os.pyc matches /usr/lib/python2.7/os.py
import os # precompiled from /usr/lib/python2.7/os.pyc
import errno # builtin
import posix # builtin
# /usr/lib/python2.7/posixpath.pyc matches /usr/lib/python2.7/posixpath.py
import posixpath # precompiled from /usr/lib/python2.7/posixpath.pyc
# /usr/lib/python2.7/stat.pyc matches /usr/lib/python2.7/stat.py
import stat # precompiled from /usr/lib/python2.7/stat.pyc
# /usr/lib/python2.7/genericpath.pyc matches /usr/lib/python2.7/genericpath.py
import genericpath # precompiled from /usr/lib/python2.7/genericpath.pyc
# /usr/lib/python2.7/warnings.pyc matches /usr/lib/python2.7/warnings.py
import warnings # precompiled from /usr/lib/python2.7/warnings.pyc
# /usr/lib/python2.7/linecache.pyc matches /usr/lib/python2.7/linecache.py
import linecache # precompiled from /usr/lib/python2.7/linecache.pyc
# /usr/lib/python2.7/types.pyc matches /usr/lib/python2.7/types.py
import types # precompiled from /usr/lib/python2.7/types.pyc
# /usr/lib/python2.7/UserDict.pyc matches /usr/lib/python2.7/UserDict.py
import UserDict # precompiled from /usr/lib/python2.7/UserDict.pyc
# /usr/lib/python2.7/_abcoll.pyc matches /usr/lib/python2.7/_abcoll.py
import _abcoll # precompiled from /usr/lib/python2.7/_abcoll.pyc
# /usr/lib/python2.7/abc.pyc matches /usr/lib/python2.7/abc.py
import abc # precompiled from /usr/lib/python2.7/abc.pyc
# /usr/lib/python2.7/_weakrefset.pyc matches /usr/lib/python2.7/_weakrefset.py
import _weakrefset # precompiled from /usr/lib/python2.7/_weakrefset.pyc
import _weakref # builtin
# /usr/lib/python2.7/copy_reg.pyc matches /usr/lib/python2.7/copy_reg.py
import copy_reg # precompiled from /usr/lib/python2.7/copy_reg.pyc
# /usr/lib/python2.7/traceback.pyc matches /usr/lib/python2.7/traceback.py
import traceback # precompiled from /usr/lib/python2.7/traceback.pyc
# /usr/lib/python2.7/sysconfig.pyc matches /usr/lib/python2.7/sysconfig.py
import sysconfig # precompiled from /usr/lib/python2.7/sysconfig.pyc
# /usr/lib/python2.7/re.pyc matches /usr/lib/python2.7/re.py
import re # precompiled from /usr/lib/python2.7/re.pyc
# /usr/lib/python2.7/sre_compile.pyc matches /usr/lib/python2.7/sre_compile.py
import sre_compile # precompiled from /usr/lib/python2.7/sre_compile.pyc
import _sre # builtin
# /usr/lib/python2.7/sre_parse.pyc matches /usr/lib/python2.7/sre_parse.py
import sre_parse # precompiled from /usr/lib/python2.7/sre_parse.pyc
# /usr/lib/python2.7/sre_constants.pyc matches /usr/lib/python2.7/sre_constants.py
import sre_constants # precompiled from /usr/lib/python2.7/sre_constants.pyc
# /usr/lib/python2.7/_sysconfigdata.pyc matches /usr/lib/python2.7/_sysconfigdata.py
import _sysconfigdata # precompiled from /usr/lib/python2.7/_sysconfigdata.pyc
# /usr/lib/python2.7/_sysconfigdata_nd.pyc matches /usr/lib/python2.7/_sysconfigdata_nd.py
import _sysconfigdata_nd # precompiled from /usr/lib/python2.7/_sysconfigdata_nd.pyc
# /usr/lib/python2.7/sitecustomize.pyc matches /usr/lib/python2.7/sitecustomize.py
import sitecustomize # precompiled from /usr/lib/python2.7/sitecustomize.pyc
import encodings # directory /usr/lib/python2.7/encodings
# /usr/lib/python2.7/encodings/__init__.pyc matches /usr/lib/python2.7/encodings/__init__.py
import encodings # precompiled from /usr/lib/python2.7/encodings/__init__.pyc
# /usr/lib/python2.7/codecs.pyc matches /usr/lib/python2.7/codecs.py
import codecs # precompiled from /usr/lib/python2.7/codecs.pyc
import _codecs # builtin
# /usr/lib/python2.7/encodings/aliases.pyc matches /usr/lib/python2.7/encodings/aliases.py
import encodings.aliases # precompiled from /usr/lib/python2.7/encodings/aliases.pyc
# /usr/lib/python2.7/encodings/utf_8.pyc matches /usr/lib/python2.7/encodings/utf_8.py
import encodings.utf_8 # precompiled from /usr/lib/python2.7/encodings/utf_8.pyc
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
# /usr/lib/python2.7/__future__.pyc matches /usr/lib/python2.7/__future__.py
import __future__ # precompiled from /usr/lib/python2.7/__future__.pyc
# /usr/lib/python2.7/subprocess.pyc matches /usr/lib/python2.7/subprocess.py
import subprocess # precompiled from /usr/lib/python2.7/subprocess.pyc
import gc # builtin
import time # builtin
import select # builtin
import fcntl # builtin
# /usr/lib/python2.7/pickle.pyc matches /usr/lib/python2.7/pickle.py
import pickle # precompiled from /usr/lib/python2.7/pickle.pyc
import marshal # builtin
# /usr/lib/python2.7/struct.pyc matches /usr/lib/python2.7/struct.py
import struct # precompiled from /usr/lib/python2.7/struct.pyc
import _struct # builtin
import binascii # builtin
import cStringIO # builtin
import psutil # directory /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/__init__.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/__init__.py
import psutil # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/__init__.pyc
import pwd # builtin
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/error.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/error.py
import psutil.error # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/error.pyc
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_compat.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_compat.py
import psutil._compat # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_compat.pyc
# /usr/lib/python2.7/collections.pyc matches /usr/lib/python2.7/collections.py
import collections # precompiled from /usr/lib/python2.7/collections.pyc
import _collections # builtin
import operator # builtin
# /usr/lib/python2.7/keyword.pyc matches /usr/lib/python2.7/keyword.py
import keyword # precompiled from /usr/lib/python2.7/keyword.pyc
# /usr/lib/python2.7/heapq.pyc matches /usr/lib/python2.7/heapq.py
import heapq # precompiled from /usr/lib/python2.7/heapq.pyc
import itertools # builtin
# /usr/lib/python2.7/bisect.pyc matches /usr/lib/python2.7/bisect.py
import bisect # precompiled from /usr/lib/python2.7/bisect.pyc
import _bisect # builtin
import _heapq # builtin
import thread # builtin
# /usr/lib/python2.7/functools.pyc matches /usr/lib/python2.7/functools.py
import functools # precompiled from /usr/lib/python2.7/functools.pyc
import _functools # builtin
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_common.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_common.py
import psutil._common # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_common.pyc
# /usr/lib/python2.7/socket.pyc matches /usr/lib/python2.7/socket.py
import socket # precompiled from /usr/lib/python2.7/socket.pyc
import _socket # builtin
dlopen("/usr/lib/python2.7/lib-dynload/_ssl.so", 2);
import _ssl # dynamically loaded from /usr/lib/python2.7/lib-dynload/_ssl.so
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_pslinux.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_pslinux.py
import psutil._pslinux # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_pslinux.pyc
# /usr/lib/python2.7/base64.pyc matches /usr/lib/python2.7/base64.py
import base64 # precompiled from /usr/lib/python2.7/base64.pyc
dlopen("/usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/_psutil_posix.so", 2);
import _psutil_posix # dynamically loaded from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/_psutil_posix.so
dlopen("/usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/_psutil_linux.so", 2);
import _psutil_linux # dynamically loaded from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/_psutil_linux.so
# /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_psposix.pyc matches /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_psposix.py
import psutil._psposix # precompiled from /usr/local/lib/python2.7/dist-packages/psutil-0.6.1-py2.7-linux-armv6l.egg/psutil/_psposix.pyc
# /usr/lib/python2.7/glob.pyc matches /usr/lib/python2.7/glob.py
import glob # precompiled from /usr/lib/python2.7/glob.pyc
# /usr/lib/python2.7/fnmatch.pyc matches /usr/lib/python2.7/fnmatch.py
import fnmatch # precompiled from /usr/lib/python2.7/fnmatch.pyc
# clear __builtin__._
# clear sys.path
# clear sys.argv
# clear sys.ps1
# clear sys.ps2
# clear sys.exitfunc
# clear sys.exc_type
# clear sys.exc_value
# clear sys.exc_traceback
# clear sys.last_type
# clear sys.last_value
# clear sys.last_traceback
# clear sys.path_hooks
# clear sys.path_importer_cache
# clear sys.meta_path
# clear sys.flags
# clear sys.float_info
# restore sys.stdin
# restore sys.stdout
# restore sys.stderr
# cleanup __main__
# cleanup[1] functools
# cleanup[1] _bisect
# cleanup[1] sysconfig
# cleanup[1] collections
# cleanup[1] zipimport
# cleanup[1] cStringIO
# cleanup[1] encodings
# cleanup[1] abc
# cleanup[1] _sysconfigdata_nd
# cleanup[1] _functools
# cleanup[1] thread
# cleanup[1] itertools
# cleanup[1] __future__
# cleanup[1] _collections
# cleanup[1] operator
# cleanup[1] _heapq
# cleanup[1] sre_constants
# cleanup[1] _warnings
# cleanup[1] _codecs
# cleanup[1] _sysconfigdata
# cleanup[1] _struct
# cleanup[1] keyword
# cleanup[1] posix
# cleanup[1] encodings.aliases
# cleanup[1] exceptions
# cleanup[1] site
# cleanup[1] sitecustomize
# cleanup[1] _weakref
# cleanup[1] _weakrefset
# cleanup[1] heapq
# cleanup[1] encodings.utf_8
# cleanup[1] bisect
# cleanup[1] codecs
# cleanup[2] subprocess
# cleanup[2] gc
# cleanup[2] struct
# cleanup[2] base64
# cleanup[2] _psutil_posix
# cleanup[2] psutil.error
# cleanup[2] signal
# cleanup[2] psutil._psposix
# cleanup[2] psutil
# cleanup[2] stat
# cleanup[2] psutil._pslinux
# cleanup[2] re
# cleanup[2] fcntl
# cleanup[2] UserDict
# cleanup[2] fnmatch
# cleanup[2] socket
# cleanup[2] traceback
# cleanup[2] os
# cleanup[2] marshal
# cleanup[2] _sre
# cleanup[2] select
# cleanup[2] posixpath
# cleanup[2] errno
# cleanup[2] _socket
# cleanup[2] binascii
# cleanup[2] os.path
# cleanup[2] pwd
# cleanup[2] sre_parse
# cleanup[2] pickle
# cleanup[2] copy_reg
# cleanup[2] sre_compile
# cleanup[2] psutil._common
# cleanup[2] linecache
# cleanup[2] _abcoll
# cleanup[2] _psutil_linux
# cleanup[2] genericpath
# cleanup[2] _ssl
# cleanup[2] warnings
# cleanup[2] glob
# cleanup[2] types
# cleanup[2] psutil._compat
# cleanup[2] time
# cleanup sys
# cleanup __builtin__
# cleanup ints: 33 unfreed ints
# cleanup floats: 4 unfreed floats


I do not know?
Posts: 36
Joined: Mon Jan 14, 2013 9:23 am
Location: Spain, Zaragoza
by timhoffman » Wed Jan 23, 2013 11:34 am
The import trace looks to me like it is successfully importing.

Can you trying just running python. Then at the >>> prompt manually try

import psutil

Cheers

Tim
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm
by ialbizu » Wed Jan 23, 2013 11:52 am
Thanks for you interes.

I try

Code: Select all
Python 3.2.3 (default, Jul  6 2012, 13:39:51)
[GCC 4.6.3] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> import psutil
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import psutil
ImportError: No module named psutil
>>>
Posts: 36
Joined: Mon Jan 14, 2013 9:23 am
Location: Spain, Zaragoza
by timhoffman » Wed Jan 23, 2013 11:57 am
Ok Here is the first issue I see.

[code]Python 3.2.3 (default, Jul 6 2012, 13:39:51)


The trace you put up here earlier was for python 2.7.

Try this again by running python2.7 instead. It looks like python3.2.x is your default for when running your script, and I bet psutils is actually only installed in python 2.7

Cheers

Tim
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm
by ialbizu » Wed Jan 23, 2013 2:08 pm
Now run, Thanks.

How, can I change the defoult version of Pyton to run?
Posts: 36
Joined: Mon Jan 14, 2013 9:23 am
Location: Spain, Zaragoza
by timhoffman » Wed Jan 23, 2013 11:04 pm
You can change the first line of the script from
#!/usr/bin/python

to

#!/usr/bin/python2.7

Alternately change the symlink in /usr/bin for python to point to python2.7

What distro are you using, it's odd that python 3 is default.

Cheers

Tim

ialbizu wrote:Now run, Thanks.

How, can I change the defoult version of Pyton to run?
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm
by ialbizu » Thu Jan 24, 2013 7:06 am
I install 2012_12_16_wheezy_raspian, but by default run th 2.7. The problem is that I open the script with IDE 3, and run python 3.

Thanks a lot for you help.
Posts: 36
Joined: Mon Jan 14, 2013 9:23 am
Location: Spain, Zaragoza