psutil: Process and System Monitoring in Python Without Shelling Out
Cross-platform lib for process and system monitoring in Python
At a glance
- What is it?
- psutil gives Python code a single API for CPU, memory, disk, network, sensor and process data across Linux, Windows, macOS, the BSDs, Solaris and AIX. The install is one pip command; the interesting part is knowing where the cross-platform abstraction holds and where it leaks.
- Who is it for?
- Adopt psutil when you need process and system metrics from inside a Python program and you want one API across Linux, Windows, macOS, the BSDs, Solaris and AIX. Do not adopt it as a long-running metrics pipeline that must survive process churn without handling NoSuchProcess.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- giampaolo/psutil11,319 ★ · +39
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| giampaolo/psutil | 11.3k | 11.3k |
39 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
What psutil replaces, and who ends up importing it
The README frames the library as a Python implementation of functionality offered by UNIX command line tools such as ps, top, free, iotop, netstat, ifconfig and lsof, and the documentation maintains a page of shell equivalents. That framing is the clearest statement of the problem: a Python program that needs to know how much memory a machine has, which processes are running, or how many bytes left the network interface normally has to spawn a subprocess, parse human-readable output, and then cope with the fact that the same command prints different columns on macOS than it does on Linux.
psutil removes the parsing layer. The return values are named tuples, so psutil.virtual_memory() returns an svmem with fields like total, available, percent, used and free, and psutil.disk_usage('/') returns an sdiskusage with total, used, free and percent. The audience is fairly narrow but deep: monitoring agents, container and job supervisors, profiling tools, test harnesses that want to assert on resource use, and any script that currently wraps ps.
psutil is not a metrics server. It has no storage, no scrape endpoint and no alerting. It answers questions about the machine it runs on, at the moment it is asked.
The platform matrix behind one import
The abstraction is not pure Python. According to the repository layout, psutil ships a compiled extension built through setuptools, with C sources under psutil/arch, and setup.py selects preprocessor macros per platform, including PSUTIL_POSIX and PSUTIL_BSD, and defines PSUTIL_SIZEOF_PID_T from struct.calcsize('l'). That means installing psutil on a platform with no prebuilt wheel requires a working C toolchain,.
The supported list in the README is Linux, Windows, macOS, FreeBSD, OpenBSD, NetBSD, Sun Solaris and AIX. The README does not enumerate which functions are missing on which platform; it points to https://psutil.io/install/ for platform-specific details and to the API overview and API reference for the full surface. Treat that pointer as the real specification. A call that works on Linux may be absent or may raise on another system, and the only reliable way to know is the per-platform notes in the API reference.
The data flow itself is simple. Each call reads from the kernel interface for that OS and returns a named tuple. cpu_percent with an interval argument blocks for that interval to compute a delta, which is the one place where the API quietly costs you wall-clock time.
How to install psutil and read your first values
The README gives one install command. Run it in the interpreter or virtual environment you intend to use, because psutil builds a platform-specific extension and a wheel installed into one environment is not visible to another.
pip install psutilAfter that, the README's first CPU example is the quickest sanity check. Passing percpu=True returns one value per logical CPU, and interval=1 makes the call block for one second to measure the delta rather than reporting since-boot averages.
import psutil
psutil.cpu_percent(interval=1, percpu=True)
psutil.cpu_count(logical=False)
psutil.virtual_memory()In the README example, cpu_percent(percpu=True) returns four values, [4.0, 6.9, 3.7, 9.2], while cpu_count(logical=False) returns 2. The memory call returns an svmem tuple with total, available, percent, used and free fields. If you see an ImportError instead, the interpreter that ran pip is not the one running your script.
The process side is a separate object model. psutil.Process(7055) takes a PID, and the resulting object exposes name(), exe(), cpu_percent(interval=1.0), memory_info(), net_connections(kind='tcp') and open_files(). For a survey of everything running, the README iterates with a field list.
for p in psutil.process_iter(['pid', 'name']):
print(p.snapshot.pid, p.snapshot.name)The README shows output beginning with 1 systemd, 2 kthreadd, 3 ksoftirqd/0 on Linux. On Windows the same loop returns different names, which is the point of the abstraction.
Where the cross-platform promise leaks
The abstraction is a common shape, not identical semantics. psutil.net_connections(kind='tcp') returns sconn tuples with fd, family, type, laddr, raddr, status and pid, but the README's own example shows the process-level variant, p.net_connections(kind='tcp'), returning pconn tuples without a pid field. The two calls look interchangeable and are not.
The bigger practical hazard is process churn. The README does not document what happens when a PID disappears between the moment you obtain it and the moment you call a method on it. Any real monitoring loop has to treat a process handle as something that can become invalid, and the design gives you no way to pin a process in place. If your code assumes p.name() always succeeds, it will fail on a busy machine.
Sensors are the least portable area. sensors_temperatures() and sensors_battery() are documented with Linux-style output, with sensor keys like coretemp and shwtemp tuples carrying label, current, high and critical. The README does not claim these work everywhere, and the platform list is much wider than the sensor coverage realistically is. If temperature data is the reason you are here, verify it on the exact hardware and OS before designing around it.
Finally, psutil is a library, not a service. It cannot tell you about another host, it keeps no history, and two calls a second apart are two independent reads. Anything that needs trends has to store the samples itself.
psutil compared with reading /proc or calling ps directly
The alternative most engineers already have installed is the shell tooling itself. A script can run ps aux, free, or read /proc directly, and on Linux that is genuinely simpler: no compiled extension, no wheel to match against the interpreter, and no abstraction to learn. The difference in approach is that shelling out gives you text that is stable for the machine you are on, while psutil gives you typed fields that are stable across machines. If your code only ever runs on one Linux distribution, the shell version has fewer moving parts.
The other realistic alternative is a full monitoring agent, where psutil is often the collection layer rather than the competitor. The distinction is scope: an agent adds scheduling, transport, storage and alerting, and psutil adds none of those. Choosing psutil means you are building the surrounding system yourself, which is the right call when the metrics feed an application's own logic rather than a dashboard.
psutil.io maintains its own alternatives page, which is worth reading before you decide, since it is the project's own comparison rather than a third party's.
Licence, maintenance and the cost of upgrading
psutil is released under BSD-3-Clause, and the LICENSE file sits at the top level of the repository. That is a permissive licence, and the practical implication for most teams is that you can ship it inside a proprietary product provided you keep the copyright notice and licence text with the distribution. This is a description of the licence identifier, not legal advice; if you are redistributing a modified copy or bundling it into a device image, have your own counsel read the actual LICENSE file.
The repository is not archived and the last push was on 2026-11-01, which is recent enough that the codebase is being touched. The repository has no GitHub releases, so pin the version you install and read HISTORY.rst before moving it.
Upgrade cost is dominated by the compiled extension. pyproject.toml requires setuptools>=75.3.4 and notes that this is the latest version supporting Python 3.8, so the build backend is deliberately held back for older interpreters. The repository also defines PEP 735 dependency groups for build, test, lint, dev and docs, installed with pip install --group <name> or the make install-pydeps-* targets. That structure matters if you build from source on a platform without wheels: you inherit the same toolchain expectations the project uses for its own CI. If you install wheels, upgrades are a version bump and a re-run of your tests.
Editorial conclusion
Adopt psutil when you need process and system metrics from inside a Python program and you want one API across Linux, Windows, macOS, the BSDs, Solaris and AIX. Do not adopt it as a long-running metrics pipeline that must survive process churn without handling NoSuchProcess. Before you commit, run psutil.cpu_percent, psutil.virtual_memory and a psutil.process_iter loop on every target OS, then compare the field values and error behaviour against the psutil.io API reference for that platform.
Frequently asked questions
What is psutil used for?
It retrieves information about running processes and system utilization (CPU, memory, disks, network, sensors) from Python. The README lists system monitoring, profiling, limiting process resources and managing running processes as the main uses.
Is psutil built into Python?
No. The README gives pip install psutil as the install step, and the repository ships a compiled extension built with setuptools, so it is a separate package rather than part of the standard library.
How do you pronounce psutil?
The README titles the project "Process and System Utilities for Python", and the project documentation lives at https://psutil.io.
Why is the psutil module not found in Python?
The most likely cause is that psutil was installed into a different interpreter or virtual environment than the one running your code, since the README's install step is a single pip install psutil.
How do you install psutil on Windows, Linux or macOS?
The README gives one command, pip install psutil, and points to https://psutil.io/install/ for platform-specific details. All three systems are on the supported platform list.
How do you use psutil cpu_percent?
The README calls psutil.cpu_percent(interval=1, percpu=True) and shows a list with one value per logical CPU, such as [4.0, 6.9, 3.7, 9.2]. Passing interval makes the call block for that many seconds to measure a delta.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/giampaolo-psutil)Star history chart for your README
[](https://hysenlabs.com/projects/giampaolo-psutil)Was this useful?