Skip to main content

psutil-android

psutil, repackaged so it installs and imports as psutil inside Termux on Android — no compiler, no NDK, no source build needed on-device.

⚠️ Termux only. This does not run on stock Android, Pydroid, QPython, Chaquopy, or any other embedded-Python runtime. See Why this is Termux-specific below for exactly why, verified via readelf.

Structure

psutil/
  _native/
    aarch64/_psutil_linux.abi3.so, meta.json
    arm/_psutil_linux.abi3.so, meta.json
    i686/_psutil_linux.abi3.so, meta.json
    x86_64/_psutil_linux.abi3.so, meta.json
  _native_loader.py   <- picks the right .so for platform.machine() at import time
  _android_compat.py  <- if loading fails, gives an exact reason instead of
                          a bare "cannot open shared object file"
  __init__.py, _common.py, _pslinux.py, ...   <- upstream psutil, unmodified

Each .so is extracted from Termux's own python-psutil package build (ghcr.io/termux/package-builder + termux/termux-packages' actual recipe), so it's linked correctly against that arch's Termux libc/ libpython — not a generic NDK cross-compile guess. meta.json next to each .so is generated from the binary's real NEEDED entries (.github/scripts/gen_meta.py, via readelf), not hand-typed, so it can't drift from what the binary actually requires.

As of the current release, all four arches (aarch64, arm, i686, x86_64) are built by CI and bundled in every published wheel — one wheel works across every Termux-supported CPU. _native_loader.py auto-selects the right one at import time.

Why this is Termux-specific, not "any Android device"

Every bundled .so is hard-linked (RUNPATH) against Termux's own runtime, confirmed via readelf -d on all four arches:

RUNPATH: /data/data/com.termux/files/usr/lib
NEEDED:  libandroid-support.so, libpython3.14.so, libc.so

So even with every arch bundled, this only runs where all of the following hold:

  • Termux is installed (not stock Android, not Pydroid/QPython/ Chaquopy — none of those have libandroid-support.so or Termux's libc.so shim)
  • CPU arch matches one of the bundled binaries (aarch64/arm/i686/x86_64 covers every arch Termux itself ships for)
  • Termux's Python minor version matches what that arch's binary was linked against (currently 3.14.x for all four, recorded per-arch in meta.json; each Termux Python update can require a rebuild — just re-run the release workflow)

When any of that doesn't hold, import fails with a specific diagnosis (_android_compat.py), not a cryptic OS error — and suggests the fallback: pkg install clang make && pip install psutil, which compiles real upstream psutil from source on-device and isn't tied to any of the above at all. That's the actually version-proof path; the bundled binaries exist to skip needing a compiler on-device.

Tested on:

Linux localhost 5.10.136-android12-9-00005-gf9a66cbe7091-ab9177899 #1 SMP PREEMPT
Fri Oct 14 05:14:18 UTC 2022 aarch64 Android

CI: building and releasing every arch

Three workflows, all Android/Termux-specific:

  • build-native.yml — matrix build across aarch64, arm, i686, x86_64 using Termux's package builder. Runs on manual dispatch or as a reusable workflow. Uploads one native-<arch> artifact per arch (.so + generated meta.json).
  • release.yml — on a v* tag push (or manual dispatch), calls build-native.yml, drops every arch's output into src/psutil/_native/<arch>/, builds the wheel + sdist, verifies via unzip -l that all four arches actually landed inside the wheel, publishes both as GitHub Release assets, then publishes the same wheel + sdist to PyPI (tag pushes only, via PyPI Trusted Publishing — no API token stored in the repo).

To produce a real multi-arch release:

git push origin main
git tag v7.2.4 && git push origin v7.2.4
# Actions tab -> release -> wait -> GitHub Release + PyPI both updated

One-time PyPI setup (before the first tag push):

  1. In this repo's Settings → Environments, create an environment named pypi (matches environment: pypi in release.yml's publish-pypi job — Trusted Publishing is scoped to it).
  2. On PyPI — https://pypi.org/manage/project/psutil-android/settings/publishing/ for an existing project, or https://pypi.org/manage/account/publishing/ if psutil-android hasn't been published yet — add a Trusted Publisher with:
    • Owner: cumulus13, Repository: psutil-android
    • Workflow: release.yml
    • Environment name: pypi

No secret needed after that — PyPI trusts the GitHub Actions OIDC token scoped to that environment.

Install

From PyPI:

pip install psutil-android

From a downloaded wheel or the release assets:

pip install psutil_android-7.2.4-py3-none-any.whl

Either way it installs as the psutil package name — don't install alongside real psutil in the same environment.

Usage

import psutil
psutil.cpu_percent(interval=1)
psutil.virtual_memory()
psutil.disk_partitions()

Provenance

This is Giampaolo Rodola's psutil (BSD-3-Clause, see LICENSE), unmodified at the Python level. There is no dedicated upstream "psutil for Android" project — Android support has been an open, unresolved request on giampaolo/psutil for years (issues #913, #2611, #2743). This package fills that gap for Termux users.

License

BSD 3-Clause, inherited from upstream psutil. See LICENSE.

👤 Maintainer

Hadi Cahyadi

Buy Me a Coffee

Donate via Ko-fi

Support me on Patreon

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

psutil_android-7.2.5.tar.gz (132.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

psutil_android-7.2.5-py3-none-any.whl (147.2 kB view details)

Uploaded Python 3

File details

Details for the file psutil_android-7.2.5.tar.gz.

File metadata

  • Download URL: psutil_android-7.2.5.tar.gz
  • Upload date:
  • Size: 132.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for psutil_android-7.2.5.tar.gz
Algorithm Hash digest
SHA256 67f9fa97975bedb019ed1594704292030a69fc1618c51e564accb7d4457ecf20
MD5 b3de811a3b63c15c307c6471788e26c6
BLAKE2b-256 271fdc5acd0409b28855a5d1da31b626d81940a1029ecdaec0ba264141eba033

See more details on using hashes here.

Provenance

The following attestation bundles were made for psutil_android-7.2.5.tar.gz:

Publisher: release.yml on cumulus13/psutil-android

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file psutil_android-7.2.5-py3-none-any.whl.

File metadata

  • Download URL: psutil_android-7.2.5-py3-none-any.whl
  • Upload date:
  • Size: 147.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for psutil_android-7.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 dbecb6c046a12319e728fccdaea74ef5721b764361d6a48ff34db635a46acf25
MD5 7a46327e38cd3e53ebb2432c96747e8d
BLAKE2b-256 1bb07edf40f181fc0493508359ddc0637132da435996504961aaf6dabb4e7faf

See more details on using hashes here.

Provenance

The following attestation bundles were made for psutil_android-7.2.5-py3-none-any.whl:

Publisher: release.yml on cumulus13/psutil-android

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page