picologging: a fast logging library that keeps the standard library API
An optimized logging library for Python
At a glance
- What is it?
- picologging is Microsoft's C accelerated logging library for Python, designed as a drop-in replacement for the standard library logging module, with the same API and a claimed speedup of four to seventeen times. The repository builds a native extension with scikit-build and CMake, and the README marks the project as beta with incomplete features.
- Who is it for?
- picologging suits a Python service whose logging is hot enough to matter, since the drop-in design means a single import change and the same handlers, formatters and configuration you already use, with a C extension doing the formatting work.
- Can I use it commercially?
- Yes. MIT 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 15 days 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 October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The same API, a different implementation
picologging is described as a high-performance logging library for Python, and the README states plainly that it is four to seventeen times faster than the logging module in the standard library.
The design intent is the first sentence of the usage section: it is designed to be used as a drop-in replacement for applications which already use logging, and it supports the same API as the logging module.
That is the whole selling point and it is a serious constraint on the design. A logging library that wants to be a drop-in replacement cannot change the semantics of a handler, cannot rename a method, and cannot make the formatter behave differently. So the speed has to come from somewhere other than the interface, and in a library like this that means the work of formatting a record and dispatching it to handlers, which is where the standard library spends time in Python.
There is a warning at the top of the README that deserves equal billing with the performance claim. The project is in beta, and there are some incomplete features, with a link to the limitations page in the documentation. That page is the document to read before you rely on a specific behaviour.
The project is MIT licensed, hosted by Microsoft, with the documentation on a GitHub Pages site and the package published on PyPI and on conda-forge.
Using it is an import change
The usage section is short enough to quote.
import picologging as logging
logging.basicConfig()
logger = logging.getLogger()
logger.info("A log message!")
logger.warning("A log message with %s", "arguments")You import the module under the name of the standard library one, and everything else in your codebase keeps working. The README adds a detail that matters in practice: this patches all the loggers registered to use picologging loggers and formatters.
That is a stronger statement than it looks. It means the change is not per logger you create but global, so a library inside your application that logs through the standard library module will also be routed through picologging once the import has happened, as long as it does not capture the module reference at import time in a way that predates your change.
For an application that logs a lot, this is the difference between logging being a measurable part of your request latency and logging being free. For an application that logs a little, the same change is a risk with no upside, which is why the limitations matter more than the benchmark table.
The laziness in the example is also the API in miniature: the message with a percent placeholder and a separate argument is the deferred formatting form, and it is the one worth using, because a logger that is filtered out never pays for the string formatting.
What the benchmarks actually show
The README gives a sample benchmark table, run with the richbench command on the benchmarks directory with the markdown output, and it lists results from macOS 11.
The table has four rows and two sets of numbers, the standard library in the first set and picologging in the second, with the speedup in brackets.
The slowest case for the standard library is a debug level logger calling debug with no arguments, at a mean of 0.578, against 0.033 for picologging, which is the 17.7 times figure in the table. The same call with arguments is 0.601 against 0.048, or 12.4 times.
The other two rows are an info level logger calling debug, which is a call that should be filtered out entirely, and they show the smallest gains: 0.013 against 0.003, or 4.8 times, and 4.4 times with arguments.
Those last two rows are the honest part of the table and worth reading carefully. A filtered call is the cheapest thing a logger does, and even there the standard library takes thirteen times longer than picologging, which tells you that the overhead is spread across the whole call rather than concentrated in the formatting. It also means that the headline seventeen times figure comes from the case where a debug call actually emits a record, which is the worst case for the standard library and the best case for the library you are replacing.
Either way, the argument for the library is that the absolute numbers are small in both columns, and the relative difference matters only when you log heavily.
Installing it
Installation is the usual two routes.
pip install picologgingconda install -c conda-forge picologgingThe PyPI badge lists the Python versions the package supports, and the setup configuration is more specific: it declares support for Python 3.7 through 3.12, requires Python 3.7 or later, and installs no runtime dependencies at all.
That last point is what makes the drop-in claim clean. There is nothing to resolve, no transitive dependency to audit and no version conflict to think about, which for a logging library that sits in everyone's import graph is the property that matters most.
The build configuration shows why it is fast and also what it costs. The package is built with setuptools and scikit-build, which drives CMake, with a minimum CMake version and Ninja as the generator. The native extension is compiled, so what you install is a binary wheel for your platform.
The wheel matrix is spelled out in the build configuration, and it is worth reading before you adopt the library. macOS builds for x86_64 and for the universal architecture, with a deployment target of 10.15. Linux builds for i686, x86_64 and aarch64. Windows builds for x86, AMD64 and ARM64. The build skips the musl based Linux builds and PyPy entirely, and skips the Windows on ARM64 tests.
So on a musl based Alpine image, or on PyPy, there is no wheel and you are compiling from source.
Building the extension and running the tests
The local development section starts with a dev container that sets up an appropriate environment, and the README says that if you install the Dev Containers extension for VS Code, opening the project should prompt you to open it in that container.
Once inside, three commands set you up.
pip install -e ".[dev]"
pre-commit install
python setup.py build_ext --inplace --build-type DebugThe third of those is the one that catches people. The README says to run the build command whenever you make changes to the files, which is the giveaway that this is a compiled extension: editing the C sources has no effect until you rebuild.
The development extras are listed in the setup configuration and are a good description of the project's testing approach: the test framework, a coverage plugin, a property based testing library, a plugin for rerunning flaky tests, a formatter, the pre-commit hooks, and a rich dependency for the benchmark output. The memray extras are separate, which tells you that memory profiling has its own optional dependency set.
The continuous integration uses the standard wheel building tool, with the test command running the unit tests in development mode, and the unit tests are a separate directory from the slow tests at the repository root.
Debugging the C code, and stepping into CPython
The README includes one of the more thorough debugging guides you will find in a project README, and it is for a specific reason: the interesting bugs in this library are in C, and they are only reproducible inside the interpreter.
The first step is a launch configuration for Visual Studio that runs the tests under the gdb debugger.
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch pytest",
"type": "cppdbg",
"request": "launch",
"program": "/usr/local/bin/python",
"args": ["-m", "pytest", "tests"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",With that, you can press the run and debug button and use breakpoint debugging in the C code, which is how you would find out why a log record came out formatted in an unexpected way.
The harder case is stepping into the interpreter itself, and the README gives a four step procedure for it. You check out the tagged branch for the dev container's Python version into the workspaces directory, which may need elevated permissions, then follow the instructions in the CPython readme to compile it. Then you add a source file mapping to the launch configuration so the debugger knows where the Python sources live, and a setup command that sets the auto-load safe path so gdb is allowed to load the debug information from that directory.
The reason for the procedure is the auto-load safety rule in gdb, which blocks loading debug information from paths that gdb does not trust. Without the safe path setting, the debugger simply refuses to step into the interpreter.
Contributing, licensing and the state of the project
Contributions are welcome and most require a Contributor License Agreement, with a bot that checks whether you need to provide one and decorates the pull request accordingly. The README says you only need to do this once across all repositories using that agreement. The project has adopted the Microsoft Open Source Code of Conduct.
The licensing section deserves a careful read. The project itself is MIT licensed, and the README explains that some components of the package come from the CPython 3.11 logging library for compatibility reasons, with CPython under the PSF licence and the logging module itself copyright Vinay Sajip. There is also a trademarks section noting that the package may contain trademarks or logos of projects, products or services, that authorised use of Microsoft trademarks follows Microsoft's guidelines, and that third party trademarks remain subject to their own policies.
That is a slightly unusual combination, and it follows from the design. A drop-in replacement that must behave identically to the standard library cannot avoid being derived from it, so the attribution is there rather than hidden.
On maintenance, the release tags are 0.9.4 from 2024-09-13, 0.9.3 from 2023-09-29 and 0.9.2 from 2023-05-17, and the last push was on 2026-10-08. The package version in the setup configuration is still 0.9.4, and the classifier says the development status is beta.
So the project is alive but not releasing quickly, and the honest summary is the warning at the top of the README: beta, with incomplete features listed on a limitations page, and a performance claim that is real but only worth paying attention to if logging is hot in your application.
Editorial conclusion
picologging suits a Python service whose logging is hot enough to matter, since the drop-in design means a single import change and the same handlers, formatters and configuration you already use, with a C extension doing the formatting work. It is the wrong choice for a library that must run on interpreters without a compiler, since the wheels are built for CPython on specific platforms and the project skips musl and PyPy, and the wrong choice if you need a stable release, since the project is in beta with incomplete features. Verify first which of the standard library behaviours the limitations page lists as missing for your case, that a wheel exists for your platform and Python version, and whether your deployment can install a binary extension at all.
Frequently asked questions
What is picologging?
It is a high-performance logging library for Python from Microsoft, designed as a drop-in replacement for the standard library logging module with the same API, and it is reported as four to seventeen times faster.
How do I switch an application over to picologging?
You import picologging under the name of the standard library module. The README notes that this patches all the loggers registered to use picologging loggers and formatters, so it applies across the application rather than per logger.
Which platforms has picologging been built for?
The wheel configuration builds for macOS on x86_64 and universal2, Linux on i686, x86_64 and aarch64, and Windows on x86, AMD64 and ARM64. The build skips the musl based Linux builds and PyPy, so there is no wheel for those.
Is picologging production ready?
The README carries a warning that the project is in beta with some incomplete features, and links to a limitations page in the documentation. The setup metadata also classifies the development status as beta.
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/microsoft-picologging)Was this useful?