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.soor Termux'slibc.soshim) - 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 acrossaarch64,arm,i686,x86_64using Termux's package builder. Runs on manual dispatch or as a reusable workflow. Uploads onenative-<arch>artifact per arch (.so+ generatedmeta.json).release.yml— on av*tag push (or manual dispatch), callsbuild-native.yml, drops every arch's output intosrc/psutil/_native/<arch>/, builds the wheel + sdist, verifies viaunzip -lthat 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):
- In this repo's Settings → Environments, create an environment named
pypi(matchesenvironment: pypiinrelease.yml'spublish-pypijob — Trusted Publishing is scoped to it). - On PyPI — https://pypi.org/manage/project/psutil-android/settings/publishing/
for an existing project, or https://pypi.org/manage/account/publishing/
if
psutil-androidhasn't been published yet — add a Trusted Publisher with:- Owner:
cumulus13, Repository:psutil-android - Workflow:
release.yml - Environment name:
pypi
- Owner:
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
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67f9fa97975bedb019ed1594704292030a69fc1618c51e564accb7d4457ecf20
|
|
| MD5 |
b3de811a3b63c15c307c6471788e26c6
|
|
| BLAKE2b-256 |
271fdc5acd0409b28855a5d1da31b626d81940a1029ecdaec0ba264141eba033
|
Provenance
The following attestation bundles were made for psutil_android-7.2.5.tar.gz:
Publisher:
release.yml on cumulus13/psutil-android
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
psutil_android-7.2.5.tar.gz -
Subject digest:
67f9fa97975bedb019ed1594704292030a69fc1618c51e564accb7d4457ecf20 - Sigstore transparency entry: 2367464358
- Sigstore integration time:
-
Permalink:
cumulus13/psutil-android@6c253302ea90a8b9fd70897ac510a7b675626f27 -
Branch / Tag:
refs/tags/v7.2.5 - Owner: https://github.com/cumulus13
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6c253302ea90a8b9fd70897ac510a7b675626f27 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbecb6c046a12319e728fccdaea74ef5721b764361d6a48ff34db635a46acf25
|
|
| MD5 |
7a46327e38cd3e53ebb2432c96747e8d
|
|
| BLAKE2b-256 |
1bb07edf40f181fc0493508359ddc0637132da435996504961aaf6dabb4e7faf
|
Provenance
The following attestation bundles were made for psutil_android-7.2.5-py3-none-any.whl:
Publisher:
release.yml on cumulus13/psutil-android
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
psutil_android-7.2.5-py3-none-any.whl -
Subject digest:
dbecb6c046a12319e728fccdaea74ef5721b764361d6a48ff34db635a46acf25 - Sigstore transparency entry: 2367464475
- Sigstore integration time:
-
Permalink:
cumulus13/psutil-android@6c253302ea90a8b9fd70897ac510a7b675626f27 -
Branch / Tag:
refs/tags/v7.2.5 - Owner: https://github.com/cumulus13
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6c253302ea90a8b9fd70897ac510a7b675626f27 -
Trigger Event:
push
-
Statement type: