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.
  · 6 min read · Updated apr 2024 · General Python Tutorials

Turn your code into any language with our Code Converter. It's the ultimate tool for multi-language programming. Start converting now!

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

In the end, I'll show you how to extract GPU information (if you have one, of course) in Python using GPUtil.

There are quite popular tools to extract system and hardware information in Linux, such as lshw, uname and hostnamectl. However, we'll be using the  psutil library in Python so it can run on all operating systems and get almost identical results.

Here is the table of contents 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 the necessary modules:

import psutil
import platform
from datetime import datetime

Let's make a function that converts a 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 the 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 the 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 the 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 the 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}%")

The 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 returns 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)}")

The net_if_addrs() function returns the addresses associated with each network interface card installed on the system. For extracting detailed network usage, check this tutorial that's dedicated to network usage monitoring with psutil.

Alright, here is the 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 the fan's RPM (Revolutions Per Minute) and also psutil.sensors_temperatures() to get various devices' temperatures.

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 print 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

Conclusion

Great, now you can integrate this information into 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.

You can get the complete tutorial code here.

Learn Also: How to Send Emails in Python.

Happy Coding ♥

Take the stress out of learning Python. Meet our Python Code Assistant – your new coding buddy. Give it a whirl!

View Full Code Create Code for Me
Sharing is caring!



Read Also



Comment panel

    Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!