1. Project Overview & Quickstart (giampaolo/psutil)
File: docs/DEVGUIDE.rst
Development guide
.. seealso:: Contributing to psutil project <https://github.com/giampaolo/psutil/blob/master/CONTRIBUTING.md>_
Build, setup and test
psutil makes extensive use of C code, so a C compiler and the Python
development headers are required. First clone the repository:.. code-block:: bash
git clone https://github.com/giampaolo/psutil.git
cd psutilOn Linux, FreeBSD, OpenBSD, NetBSD and Solaris, install the system deps:
.. code-block:: bash
make install-sysdeps # compiler + python headers
make install-sysdeps-test # CLI tools used by testsOn macOS, AIX and Windows there's no such target, see
:ref:install_from_source. Then, everywhere:.. code-block:: bash
make install-pydeps-dev # python development deps (linters, etc)
make build # compile the C extension in place
make testmake(via the :src:Makefile) is used for building, testing and general
development tasks, including on Windows (see below):.. code-block:: bash
make clean
make test
make test-parallel
make test-memleaks
make coverage
make lint-all
make fix-all
make uninstall
make helpTo run a specific test:
.. code-block:: none
make test ARGS=tests/test_system.py
make buildcompiles the extension in place, so you can import psutil
straight from the repo. No need to install it.Don't use
sudo, except for theinstall-sysdeps-*targets, which
invoke it themselves when needed.To target a specific Python version, pass
PYTHONto every step, so that
the extension is built by the same interpreter that runs the tests:.. code-block:: none
make install-pydeps-dev PYTHON=python3.13
make build PYTHON=python3.13
make test PYTHON=python3.13
Windows
The recommended way to develop on Windows is to use
make.For the build tools, Git Bash and GNU Make setup see :ref:
install_windows.Once inside a Git Bash shell, run:
.. code-block:: bash
make install-pydeps-dev
make build
make test-parallel
.. _devguide_debug_mode:
Debug mode
If you need to debug unusual situations or report a bug, you can enable debug
mode via the :envvar:PSUTIL_DEBUG environment variable. In this mode, psutil
may print additional information to stderr. Usually these are non-severe error
conditions that are ignored instead of causing a crash. Unit tests
automatically run with debug mode enabled. To enable debug mode in UNIX (or on
Windows + Bash):
.. code-block:: none
$ PSUTIL_DEBUG=1 python3 test_script.py
psutil-debug [psutil/_psutil_linux.c:150]> setmntent() failed (ignored)
On Windows using cmd.exe:
.. code-block:: none
set PSUTIL_DEBUG=1 && python.exe test_script.py
psutil-debug [psutil/arch/windows/proc.c:56]> ReadProcessMemory -> ERROR_NOACCESS (ignored)
Coding style
All style and formatting checks are enforced locally on each git commit and
via a GitHub Actions pipeline.
- Python: follows
PEP-8_, formatted and linted withblackandruff. - C: generally follows
PEP-7_, formatted withclang-format. - Other files (
.rst,.toml,.md,.yml): validated by linters.
The pipeline re-runs all checks for consistency (make lint-all).
Run make fix-all before committing; it usually fixes Python issues (viablack and ruff) and C issues (via clang-format).
Code organization
Not every API reaches C: many are implemented in python alone (on Linux, by
parsing /proc). For those that do, a call travels down through the
platform-specific layers. Linux is used here as an example:
.. code-block:: none
import psutil
โ
โผ
psutil/init.py public API, Process class
โ
โผ
psutil/_pslinux.py python layer: parses /proc, calls into C
โ
โผ
psutil/_psutil_linux.c C extension entry point (arg parsing)
โ
โผ
psutil/arch/linux/.c platform-specific C implementation
+ arch/posix/.c shared by POSIX
+ arch/all/*.c shared by everything
Where things live:
.. code-block:: bash
psutil/init.py # Public API ("import psutil")
psutil/_common.py # Generic utilities
psutil/_ntuples.py # Named tuples returned by psutil APIs
psutil/_enums.py # Enum containers
psutil/ps{platform}.py # OS-specific python wrapper
psutil/psutil{platform}.c # OS-specific C extension (entry point)
psutil/arch/all/.c # C code common to all OSes
psutil/arch/posix/.c # C code common to POSIX OSes
psutil/arch/bsd/.c # C code common to the BSDs
psutil/arch/{platform}/.c # OS-specific C implementation
tests/test_process.py # Main process API tests
tests/test_system.py # Main system API tests
tests/test{platform}.py # OS-specific tests
Adding a new API
- Define the public API in :src:
psutil/__init__.py. - Implement it for each applicable platform in
psutil/_ps{platform}.py
(e.g. :src:psutil/_pslinux.py). - If needed, add C code in
psutil/arch/{platform}/file.c. - Add a generic test in :src:
tests/test_system.pyor
:src:tests/test_process.py. - Add a platform-specific test in
tests/test_{platform}.py. - Update :src:
docs/api.rst. - Open a pull request.
Make a pull request
- Fork psutil on GitHub.
- Clone your fork:
git clone [email protected]:YOUR-USERNAME/psutil.git - Create a branch:
git checkout -b new-feature - Stage and commit:
git add <files>thengit commit -m 'Add some feature' - Push:
git push origin new-feature - Open a pull request (see :src:
CONTRIBUTING.md).
Continuous integration
Tests run automatically on pull requests and on relevant pushes, covering all
regularly tested platforms except AIX. See.github/workflows <https://github.com/giampaolo/psutil/tree/master/.github/workflows>_.
Documentation
Source is in the :src:
docs/ <docs/>directory.To build HTML:
.. code-block:: bash
make install-pydeps-docs
cd docs/
make htmlThe documentation is hosted at https://psutil.io. It's a single version,
rebuilt and deployed automatically on every push tomaster.
Releases
For project maintainers:
- Releases are uploaded to
PyPI_ viamake release. - Git tags use the
vX.Y.Zformat (e.g.v7.2.2). - The version string is defined in :src:
psutil/__init__.py(__version__).
.. _PEP-7: https://www.python.org/dev/peps/pep-0007/
.. _PEP-8: https://www.python.org/dev/peps/pep-0008/
.. _PyPI: https://pypi.org/project/psutil/
File: docs/index.rst
.. module:: psutil
:synopsis: psutil module
.. moduleauthor:: Giampaolo Rodola [email protected]
.. title:: Home
.. ============================================================================
.. Hero
.. ============================================================================
.. raw:: html
<h1 class="hero-title">psutil</h1>
Process and System Utilities for Python.. container:: home-intro
Psutil is a cross-platform library for retrieving information about running
processes and system utilization in Python. It is useful mainly for system
monitoring, profiling, limiting process resources, and managing running
processes. Psutil implements many functionalities offered by UNIX command
line tool such as ps, top, free, iotop, netstat, ifconfig, lsof and
others.
.. ============================================================================
.. Install one-liner
.. ============================================================================
.. raw:: html
$
<code class="home-install-cmd">pip install psutil</code>
<svg class="home-install-icon-copy" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true">
<rect x="4" y="4" width="9" height="9" rx="1.2"></rect>
</svg>
<svg class="home-install-icon-check" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
</svg>
Copied.. ============================================================================
.. Platform pills
.. ============================================================================
.. raw:: html
<a class="home-platforms-label" href="platform/">Runs on</a>
<a class="home-platform-pill" href="platform/">Linux</a>
<a class="home-platform-pill" href="platform/">Windows</a>
<a class="home-platform-pill" href="platform/">macOS</a>
<a class="home-platform-pill" href="platform/">FreeBSD</a>
<a class="home-platform-pill" href="platform/">OpenBSD</a>
<a class="home-platform-pill" href="platform/">NetBSD</a>
<a class="home-platform-pill" href="platform/">Solaris</a>
<a class="home-platform-pill" href="platform/">AIX</a>.. ============================================================================
.. Feature cards
.. ============================================================================
.. raw:: html
Explore the API
<a class="home-feature-card" href="api/#cpu">
CPU
</a>
<a class="home-feature-card" href="api/#memory">
Memory
</a>
<a class="home-feature-card" href="api/#disks">
Disks
</a>
<a class="home-feature-card" href="api/#network">
Network
</a>
<a class="home-feature-card" href="api/#sensors">
Sensors
</a>
<a class="home-feature-card" href="api/#processes">
Processes
</a>.. ============================================================================
.. Quickstart code preview (tabs by category)
.. ============================================================================
.. raw:: html
Try it
.. container:: home-quickstart
.. tab-set::
.. tab-item:: CPU
.. code-block:: pycon
>>> import psutil
>>> psutil.cpu_times()
scputimes(user=3961.46, nice=169.72, system=2150.65, idle=16900.54, iowait=629.59, ...)
>>> psutil.cpu_percent(interval=1)
4.0
>>> psutil.cpu_count(logical=False)
2
>>> psutil.cpu_freq()
scpufreq(current=931.42, min=800.0, max=3500.0)
.. container:: home-tab-more
:ref:`See more โ <api-overview-cpu>`
.. tab-item:: Memory
.. code-block:: pycon
>>> import psutil
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, ...)
>>> psutil.swap_memory()
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
.. container:: home-tab-more
:ref:`See more โ <api-overview-memory>`
.. tab-item:: Disks
.. code-block:: pycon
>>> import psutil
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext4', opts='rw')]
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
>>> psutil.disk_io_counters()
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220, write_bytes=24081764, ...)
.. container:: home-tab-more
:ref:`See more โ <api-overview-disks>`
.. tab-item:: Network
.. code-block:: pycon
>>> import psutil
>>> psutil.net_io_counters(pernic=True)
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, ...),
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, ...)}
>>> psutil.net_connections(kind='tcp')
[sconn(family=2, type=1, laddr=addr('10.0.0.1', 48776), raddr=addr('93.186.135.91', 80), status='ESTABLISHED', pid=1254), ...]
>>> psutil.net_if_addrs()['wlan0']
[snicaddr(family=2, address='192.168.1.3', netmask='255.255.255.0', ...), ...]
>>> psutil.net_if_stats()['wlan0']
snicstats(isup=True, duplex=2, speed=100, mtu=1500, flags='up,broadcast,running')
.. container:: home-tab-more
:ref:`See more โ <api-overview-network>`
.. tab-item:: Sensors
.. code-block:: pycon
>>> import psutil
>>> psutil.sensors_temperatures()
{'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)],
'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)]}
>>> psutil.sensors_fans()
{'asus': [sfan(label='cpu_fan', current=3200)]}
>>> psutil.sensors_battery()
sbattery(percent=93, secsleft=16628, power_plugged=False)
.. container:: home-tab-more
:ref:`See more โ <api-overview-sensors>`
.. tab-item:: Processes
.. code-block:: pycon
>>> import psutil
>>> p = psutil.Process(7055)
>>> p.name(), p.exe(), p.cmdline()
('python3', '/usr/bin/python3', ['/usr/bin/python3', 'main.py'])
>>> p.status()
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.memory_info()
pmem(rss=3164160, vms=4410163, shared=897433, text=302694, data=2422374)
>>> p.parent(), p.children(recursive=True)
(psutil.Process(pid=4699, name='bash'), [psutil.Process(pid=29835, name='python3'), ...])
.. container:: home-tab-more
:ref:`See more โ <api-overview-processes>`.. ============================================================================
.. Adoption stats. Numbers kept in sync with adoption.rst and README.rst
.. by scripts/internal/docs/refresh_adoption_stats.py.
.. ============================================================================
.. raw:: html
Stats
<a class="home-stat" href="https://clickpy.clickhouse.com/dashboard/psutil">
390+ million
downloads per month
</a>
<a class="home-stat" href="https://github.com/giampaolo/psutil/network/dependents">
780,000+
GitHub repositories
</a>
<a class="home-stat" href="timeline/">
{{years_in_development}} years
in active development
</a>.. ============================================================================
.. Sponsors
.. ============================================================================
.. raw:: html
Sponsors.. raw:: html
:file: _sponsors.html
.. raw:: html
.. ============================================================================
.. TOC: hidden via CSS, needed by Sphinx for sidebar nav
.. ============================================================================
.. toctree::
:maxdepth: 2
:caption: Documentation
Install
API overview
API Reference
FAQ
Performance
Recipes
.. toctree::
:maxdepth: 2
:caption: Reference
Shell equivalents
Stdlib equivalents
Glossary
Platform support
Migration
.. toctree::
:maxdepth: 2
:caption: About
Who uses psutil
Alternatives
Funding
Credits
.. toctree::
:maxdepth: 2
:titlesonly:
:caption: Project
Blog
Changelog
Timeline
Development guide
General Index
File: README.rst
..
.. raw:: html
..
About
psutil is a cross-platform library for retrieving information about running
processes and system utilization (CPU, memory, disks, network, sensors)
in Python. It is useful mainly for system monitoring, profiling,
limiting process resources, and managing running processes. It
implements many functionalities offered by UNIX command line tool such as
ps, top, free, iotop, netstat, ifconfig, lsof and others (seeshell equivalents_). Psutil supports the following platforms:
- Linux
- Windows
- macOS
- FreeBSD, OpenBSD, NetBSD
- Sun Solaris
- AIX
Adoption
psutil is among thetop 100 <https://clickpy.clickhouse.com/dashboard/psutil>__ most-downloaded
packages on PyPI, with 390+ million downloads per month and 780,000+GitHub repositories <https://github.com/giampaolo/psutil/network/dependents>__
using it. See also adoptions <https://psutil.io/adoption/>__ andalternatives <https://psutil.io/alternatives/>__.
Install
.. code-block::
pip install psutilFor platform-specific details see installation <https://psutil.io/install/>_.
Documentation
psutil documentation is available at https://psutil.io.
..
Sponsors
.. raw:: html
<sup>[add your logo](https://psutil.io/funding/)</sup>..
Example usages
For the full API with more examples, see theAPI overview <https://psutil.io/api-overview/>_ andAPI reference <https://psutil.io/api/>_.
CPU
.. code-block:: python
>>> import psutil
>>> psutil.cpu_percent(interval=1, percpu=True)
[4.0, 6.9, 3.7, 9.2]
>>> psutil.cpu_count(logical=False)
2
>>> psutil.cpu_freq()
scpufreq(current=931.42, min=800.0, max=3500.0)Memory
.. code-block:: python
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, ...)
>>> psutil.swap_memory()
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)Disks
.. code-block:: python
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext', opts='rw')]
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)Network
.. code-block:: python
>>> psutil.net_io_counters(pernic=True)
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, ...),
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, ...)}
>>> psutil.net_connections(kind='tcp')
[sconn(fd=115, family=2, type=1, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
...]Sensors
.. code-block:: python
>>> psutil.sensors_temperatures()
{'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]}
>>> psutil.sensors_battery()
sbattery(percent=93, secsleft=16628, power_plugged=False)Processes
.. code-block:: python
>>> p = psutil.Process(7055)
>>> p.name()
'python3'
>>> p.exe()
'/usr/bin/python3'
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.memory_info()
pmem(rss=3164160, vms=4410163, shared=897433, text=302694, data=2422374)
>>> p.net_connections(kind='tcp')
[pconn(fd=115, family=2, type=1, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED')]
>>> p.open_files()
[popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768)]
>>>
>>> for p in psutil.process_iter(['pid', 'name']):
... print(p.pid, p.name())
...
1 systemd
2 kthreadd
3 ksoftirqd/0
..... _shell equivalents: https://psutil.io/shell-equivalents/
..
License
BSD-3
File: docs/README.md
psutil documentation
This directory is a self-contained Sphinx project that builds the psutil docs
published at https://psutil.io/. It has grown well past a plain API reference
(custom theme, a blog, social cards, its own test suite and deploy pipeline),
so this file is the map.
Build & preview
make html # one-off build into _build/html
make autoreload # live-reload server at 127.0.0.1:8000make html turns warnings into errors, same as CI.
Layout
*.rst: the doc sources.api.rstis the hand-written API reference;index.rstis the home page.blog/: blog posts, managed by the ablog extension + comments provided via
giscus.conf.py: Sphinx config: extensions, the theme,html_baseurl, OpenGraph /
sitemap / feed settings._templates/: the custom theme, built on Sphinx'sbasictheme (topbar,
sidebar, footer, layout)._static/css/,_static/js/: styles and vanilla JS (no framework)._ext/: small local Sphinx extensions._extra/robots.txt: copied verbatim to the site root.versions.json: the version selector's menu (see below).
Notable choices
- master is served at the site root (no
/en/, no/latest/); frozen past
releases live under/<version>/, listed inversions.json. - Built with the
dirhtmlbuilder, so URLs are extensionless directories
(psutil.io/faq/, no.html). - Self-hosted on GitHub Pages under the custom domain psutil.io.
- Fonts, CSS and JS are all self-hosted; no external assets.
- Social cards, sitemap and Atom feed are generated at build time and rooted at
html_baseurl.
Freezing a doc version
Add an entry to versions.json:
{ "name": "8.0", "url": "/8.0/", "note": "release", "ref": "v8.0.0" }Entries with a ref are rebuilt from it on every deploy and get an "old
version" banner. Nothing is stored, and tags publish nothing on their own.
Deleting the entry unpublishes it.
Tests
test_docs.py: offline checks on the built HTML (canonical / OG tags,
sitemap, feed, blog metadata, no external assets, ...). Run withmake test.test_docs_online.py: smoke tests against the live site (reachability,
http->https, 404 page, metadata). Run withmake test-online-doc(setsPSUTIL_DOCS_ONLINE=1).
Deploy
.github/workflows/docs.yml runs on pushes / PRs that touch docs/: lint
(make lint-rst) -> offline tests -> build -> build past versions -> deploy to
GitHub Pages -> live-site tests. Deploy and the live tests run only on push to
master, never on PRs.
2. Official Technical Reference & Guides (giampaolo/giampaolo.github.io)
File: README.md
Source code for https://gmpy.dev/ / https://giampaolo.github.io/.
Everything lives on the master branch. On every push a GitHub Actions
workflow builds the Pelican site and deploys it to GitHub Pages, so no
generated HTML is stored in the repo.
Note: content/extra/htaccess is Apache-only and applies to
https://gmpy.dev/. GitHub Pages ignores it; the .github.io mirror
relies on Pelican's own URL layout.
Setup
- Install python deps:
make install-pydeps- Run server locally (http://127.0.0.1:8000):
make serveMake a new blog post
- create a new file, e.g.
content/blog/2020/new-blog-post.rst; usemake create-blogpost
New blog post
#############
:date: 2020-06-26
:tags: announce, python
Hello world!- test it:
# after this connect to http://127.0.0.1:8000/
make clean html serve- commit and push it:
git add content/blog/2020/new-blog-post.rst
git ci -am "new blog post"
git push- the push triggers a GitHub Actions build that deploys to Pages; within a
minute or so gmpy.dev updates automatically.
Link to an internal blog post
`blog post <../2013/making-constants-part-of-your-api-is-evil>`_Image
.. raw:: html
<a href="/images/me-with-jay.jpg">
</a>File: content/blog/2025/a-brave-chrome-extension-to-reorder-tabs.md
Title: A Brave / Chrome extension to reorder new tabs
Date: 2025-04-02
Tags: js, brave, dotfiles
Authors: Giampaolo Rodola
While browsing, I almost always keep three tabs open: Gmail, Slack, and
Microsoft Teams (for work). I find it convenient to have them always in the
same position (1, 2, and 3), so I can quickly switch to them using keyboard
shortcuts (alt+1, alt+2, alt+3). While the Gmail tab remains in place,
Slack and Teams frequently move because I use them for work, closing them in
the evening and reopening them the next morning. And each time I have to
manually reposition them. To automate this process, I started looking for a
Brave (Chrome) extension but couldn't find one that fully met my needs. So, I
decided to spend a little time writing my own. It turns out it's incredibly
easy. Here's how you can create a simple Brave extension. The same process
should also work for Chrome.
- Put these 2 files in a folder:
manifest.json:
{
"manifest_version": 3,
"name": "Tab repositioner",
"version": "1.0",
"description": "Set position of new tabs",
"permissions": ["tabs"],
"background": {
"service_worker": "background.js"
}
}background.js:
function move_tab(tab, index) {
if (tab.index != index) {
console.log(`moving tab '${tab.url}' to position ${index}`);
chrome.tabs.move(tab.id, { index: index });
}
}
function move_new_tabs(changeInfo, tab) {
if ((changeInfo.status === "loading" || changeInfo.status === "complete") && tab.url) {
if (tab.url.includes("mail.google.com")) { move_tab(tab, 0); }
if (tab.url.includes("app.slack.com")) { move_tab(tab, 1); }
if (tab.url.includes("teams.microsoft.com")) { move_tab(tab, 2); }
}
}
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
move_new_tabs(changeInfo, tab);
});- Go to
brave://extensions/(chrome://extensions/for Chrome). - Enable
Developer Mode(top right). - Click
Load unpackedand select your folder. - To observe debug messages printed in the console, click on
Service Worker. - After editing
background.js, click the refresh icon to apply the changes.