How to Get Hardware and System Information in Python

Extracting and Fetching all system and hardware information such as os details, CPU and GPU information, disk and network usage in Python using platform, psutil and gputil libraries.
  · 9 min read · Updated jul 2020 · General Python Topics


As a Python developer, it is handy to use third-party libraries that does the job you actually want, instead of reinventing the wheel each time. In this tutorial, you will be familiar with psutil which is cross-platform library for process and system monitoring in Python, as well as built-in platform module to extract your system and hardware information in Python.

In the end, I'll show you how you can print GPU information (if you have one, of course) as well.

Here is the table of content of this tutorial:

  1. System Information
  2. CPU Information
  3. Memory Usage
  4. Disk Usage
  5. Network Information
  6. GPU Information

Related: How to Manipulate IP Addresses in Python using ipaddress Module.

Before we dive in, you need to install psutil:

pip3 install psutil

Open up a new python file and let's get started, importing necessary modules:

import psutil
import platform
from datetime import datetime

Let's make a function that converts large number of bytes into a scaled format (e.g in kilo, mega, giga, etc.):

def get_size(bytes, suffix="B"):
    """
    Scale bytes to its proper format
    e.g:
        1253656 => '1.20MB'
        1253656678 => '1.17GB'
    """
    factor = 1024
    for unit in ["", "K", "M", "G", "T", "P"]:
        if bytes < factor:
            return f"{bytes:.2f}{unit}{suffix}"
        bytes /= factor

System Information

We gonna need platform module here:

print("="*40, "System Information", "="*40)
uname = platform.uname()
print(f"System: {uname.system}")
print(f"Node Name: {uname.node}")
print(f"Release: {uname.release}")
print(f"Version: {uname.version}")
print(f"Machine: {uname.machine}")
print(f"Processor: {uname.processor}")

Getting the date and time the computer was booted:

# Boot Time
print("="*40, "Boot Time", "="*40)
boot_time_timestamp = psutil.boot_time()
bt = datetime.fromtimestamp(boot_time_timestamp)
print(f"Boot Time: {bt.year}/{bt.month}/{bt.day} {bt.hour}:{bt.minute}:{bt.second}")

CPU Information

Let's get some CPU information, such as total number of cores, usage, etc:

# let's print CPU information
print("="*40, "CPU Info", "="*40)
# number of cores
print("Physical cores:", psutil.cpu_count(logical=False))
print("Total cores:", psutil.cpu_count(logical=True))
# CPU frequencies
cpufreq = psutil.cpu_freq()
print(f"Max Frequency: {cpufreq.max:.2f}Mhz")
print(f"Min Frequency: {cpufreq.min:.2f}Mhz")
print(f"Current Frequency: {cpufreq.current:.2f}Mhz")
# CPU usage
print("CPU Usage Per Core:")
for i, percentage in enumerate(psutil.cpu_percent(percpu=True, interval=1)):
    print(f"Core {i}: {percentage}%")
print(f"Total CPU Usage: {psutil.cpu_percent()}%")

psutil's cpu_count() function returns number of cores, whereas cpu_freq() function returns CPU frequency as a namedtuple including current, min and max frequency expressed in Mhz, you can set percpu=True to get per CPU frequency.

cpu_percent() method returns a float representing the current CPU utilization as a percentage, setting interval to 1 (seconds) will compare system CPU times elapsed before and after a second, we set percpu to True in order to get CPU usage of each core.

Memory Usage

# Memory Information
print("="*40, "Memory Information", "="*40)
# get the memory details
svmem = psutil.virtual_memory()
print(f"Total: {get_size(svmem.total)}")
print(f"Available: {get_size(svmem.available)}")
print(f"Used: {get_size(svmem.used)}")
print(f"Percentage: {svmem.percent}%")
print("="*20, "SWAP", "="*20)
# get the swap memory details (if exists)
swap = psutil.swap_memory()
print(f"Total: {get_size(swap.total)}")
print(f"Free: {get_size(swap.free)}")
print(f"Used: {get_size(swap.used)}")
print(f"Percentage: {swap.percent}%")

virtual_memory() method returns stats about system memory usage as a namedtuple, including fields such as total (total physical memory available), available (available memory, i.e not used), used and percent (i.e percentage). swap_memory() is the same but for swap memory.

We used the previously defined get_size() function to print values in a scaled manner, as these statistics are expressed in bytes.

Disk Usage

# Disk Information
print("="*40, "Disk Information", "="*40)
print("Partitions and Usage:")
# get all disk partitions
partitions = psutil.disk_partitions()
for partition in partitions:
    print(f"=== Device: {partition.device} ===")
    print(f"  Mountpoint: {partition.mountpoint}")
    print(f"  File system type: {partition.fstype}")
    try:
        partition_usage = psutil.disk_usage(partition.mountpoint)
    except PermissionError:
        # this can be catched due to the disk that
        # isn't ready
        continue
    print(f"  Total Size: {get_size(partition_usage.total)}")
    print(f"  Used: {get_size(partition_usage.used)}")
    print(f"  Free: {get_size(partition_usage.free)}")
    print(f"  Percentage: {partition_usage.percent}%")
# get IO statistics since boot
disk_io = psutil.disk_io_counters()
print(f"Total read: {get_size(disk_io.read_bytes)}")
print(f"Total write: {get_size(disk_io.write_bytes)}")

As expected, disk_usage() function return disk usage statistics as a namedtuple, including total, used and free space expressed in bytes.

Network Information

# Network information
print("="*40, "Network Information", "="*40)
# get all network interfaces (virtual and physical)
if_addrs = psutil.net_if_addrs()
for interface_name, interface_addresses in if_addrs.items():
    for address in interface_addresses:
        print(f"=== Interface: {interface_name} ===")
        if str(address.family) == 'AddressFamily.AF_INET':
            print(f"  IP Address: {address.address}")
            print(f"  Netmask: {address.netmask}")
            print(f"  Broadcast IP: {address.broadcast}")
        elif str(address.family) == 'AddressFamily.AF_PACKET':
            print(f"  MAC Address: {address.address}")
            print(f"  Netmask: {address.netmask}")
            print(f"  Broadcast MAC: {address.broadcast}")
# get IO statistics since boot
net_io = psutil.net_io_counters()
print(f"Total Bytes Sent: {get_size(net_io.bytes_sent)}")
print(f"Total Bytes Received: {get_size(net_io.bytes_recv)}")

net_if_addrs() function return the addresses associated to each network interface card installed on the system.

Alright, here is a result output of my personal linux machine:

======================================== System Information ========================================
System: Linux
Node Name: rockikz
Release: 4.17.0-kali1-amd64
Version: #1 SMP Debian 4.17.8-1kali1 (2018-07-24)
Machine: x86_64
Processor:
======================================== Boot Time ========================================
Boot Time: 2019/8/21 9:37:26
======================================== CPU Info ========================================
Physical cores: 4
Total cores: 4
Max Frequency: 3500.00Mhz
Min Frequency: 1600.00Mhz
Current Frequency: 1661.76Mhz
CPU Usage Per Core:
Core 0: 0.0%
Core 1: 0.0%
Core 2: 11.1%
Core 3: 0.0%
Total CPU Usage: 3.0%
======================================== Memory Information ========================================
Total: 3.82GB
Available: 2.98GB
Used: 564.29MB
Percentage: 21.9%
==================== SWAP ====================
Total: 0.00B
Free: 0.00B
Used: 0.00B
Percentage: 0%
======================================== Disk Information ========================================
Partitions and Usage:
=== Device: /dev/sda1 ===
  Mountpoint: /
  File system type: ext4
  Total Size: 451.57GB
  Used: 384.29GB
  Free: 44.28GB
  Percentage: 89.7%
Total read: 2.38GB
Total write: 2.45GB
======================================== Network Information ========================================
=== Interface: lo ===
  IP Address: 127.0.0.1
  Netmask: 255.0.0.0
  Broadcast IP: None
=== Interface: lo ===
=== Interface: lo ===
  MAC Address: 00:00:00:00:00:00
  Netmask: None
  Broadcast MAC: None
=== Interface: wlan0 ===
  IP Address: 192.168.1.101
  Netmask: 255.255.255.0
  Broadcast IP: 192.168.1.255
=== Interface: wlan0 ===
=== Interface: wlan0 ===
  MAC Address: 64:70:02:07:40:50
  Netmask: None
  Broadcast MAC: ff:ff:ff:ff:ff:ff
=== Interface: eth0 ===
  MAC Address: d0:27:88:c6:06:47
  Netmask: None
  Broadcast MAC: ff:ff:ff:ff:ff:ff
Total Bytes Sent: 123.68MB
Total Bytes Received: 577.94MB

If you are using a laptop, you can use psutil.sensors_battery() to get battery information.

Also, if you are a linux user, you can use psutil.sensors_fan() to get fan's RPM (Revolutions Per Minute) and also psutil.sensors_temperatures() to get various devices' temperature.

GPU Information

psutil doesn't provide us with GPU information.Therefore, we need to install GPUtil:

pip3 install gputil

GPUtil is a Python module for getting the GPU status for NVIDIA GPUs only, it locates all GPUs on the computer, determines their availability and returns an ordered list of available GPUs. It requires the latest NVIDIA driver installed.

Also, we need to install tabulate module, which will allow us to print GPU information in a tabular way:

pip3 install tabulate

The following lines of code prints all GPUs in your machine along with their details:

# GPU information
import GPUtil
from tabulate import tabulate
print("="*40, "GPU Details", "="*40)
gpus = GPUtil.getGPUs()
list_gpus = []
for gpu in gpus:
    # get the GPU id
    gpu_id = gpu.id
    # name of GPU
    gpu_name = gpu.name
    # get % percentage of GPU usage of that GPU
    gpu_load = f"{gpu.load*100}%"
    # get free memory in MB format
    gpu_free_memory = f"{gpu.memoryFree}MB"
    # get used memory
    gpu_used_memory = f"{gpu.memoryUsed}MB"
    # get total memory
    gpu_total_memory = f"{gpu.memoryTotal}MB"
    # get GPU temperature in Celsius
    gpu_temperature = f"{gpu.temperature} °C"
    gpu_uuid = gpu.uuid
    list_gpus.append((
        gpu_id, gpu_name, gpu_load, gpu_free_memory, gpu_used_memory,
        gpu_total_memory, gpu_temperature, gpu_uuid
    ))

print(tabulate(list_gpus, headers=("id", "name", "load", "free memory", "used memory", "total memory",
                                   "temperature", "uuid")))

Here is the output in my machine:

======================================== GPU Details ========================================
  id  name              load    free memory    used memory    total memory    temperature    uuid
----  ----------------  ------  -------------  -------------  --------------  -------------  ----------------------------------------
   0  GeForce GTX 1050  2.0%    3976.0MB       120.0MB        4096.0MB        52.0 °C        GPU-c9b08d82-f1e2-40b6-fd20-543a4186d6ce

Great, now you can integrate these information on your Python monitor applications and utilities !

Check the documentation of the libraries we used in this tutorial:

You can also use psutil to monitor operating system processes, such as CPU and memory usage of each process, etc.

Finally, many of the Python concepts aren't discussed in detail here, if you feel you want to dig more to Python, I highly suggest you get one of these amazing courses:

Learn Also: How to Send Emails in Python using smtplib Module.

Happy Coding ♥

View Full Code
Sharing is caring!



Read Also





Comment panel