Development guide

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:

    git clone https://github.com/giampaolo/psutil.git
    cd psutil
    

    On Linux, FreeBSD, OpenBSD, NetBSD and Solaris, install the system deps:

    make install-sysdeps       # compiler + python headers
    make install-sysdeps-test  # CLI tools used by tests
    

    On macOS, AIX and Windows there’s no such target, see Build psutil from source. Then, everywhere:

    make install-pydeps-dev    # python development deps (linters, etc)
    make build                 # compile the C extension in place
    make test
    
  • make (via the Makefile) is used for building, testing and general development tasks, including on Windows (see below):

    make clean
    make test
    make test-parallel
    make test-memleaks
    make coverage
    make lint-all
    make fix-all
    make uninstall
    make help
    
  • To run a specific test:

    make test ARGS=tests/test_system.py
    
  • make build compiles the extension in place, so you can import psutil straight from the repo. No need to install it.

  • Don’t use sudo, except for the install-sysdeps-* targets, which invoke it themselves when needed.

  • To target a specific Python version, pass PYTHON to every step, so that the extension is built by the same interpreter that runs the tests:

    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 Windows.

  • Once inside a Git Bash shell, run:

    make install-pydeps-dev
    make build
    make test-parallel
    

Debug mode

If you need to debug unusual situations or report a bug, you can enable debug mode via the 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):

$ PSUTIL_DEBUG=1 python3 test_script.py
psutil-debug [psutil/_psutil_linux.c:150]> setmntent() failed (ignored)

On Windows using cmd.exe:

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 with black and ruff.

  • C: generally follows PEP-7, formatted with clang-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 (via black 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:

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:

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

Make a pull request

  • Fork psutil on GitHub.

  • Clone your fork: git clone git@github.com:YOUR-USERNAME/psutil.git

  • Create a branch: git checkout -b new-feature

  • Stage and commit: git add <files> then git commit -m 'Add some feature'

  • Push: git push origin new-feature

  • Open a pull request (see CONTRIBUTING.md).

Continuous integration

Tests run automatically on pull requests and on relevant pushes, covering all regularly tested platforms except AIX. See .github/workflows.

Documentation

  • Source is in the docs/ directory.

  • To build HTML:

    make install-pydeps-docs
    cd docs/
    make html
    
  • The documentation is hosted at https://psutil.io. It’s a single version, rebuilt and deployed automatically on every push to master.

Releases

For project maintainers:

  • Releases are uploaded to PyPI via make release.

  • Git tags use the vX.Y.Z format (e.g. v7.2.2).

  • The version string is defined in psutil/__init__.py (__version__).