CLI tool
abseil/abseil-py avatar
abseil/abseil-py

abseil-py: Google's flags, logging and test scaffolding as a pip package

Abseil Common Libraries (Python)

2,450 stars279 forksPythonApache-2.0

At a glance

What is it?
Abseil's Python libraries are what sits underneath many Google-adjacent command line tools, and the repository describes itself as code collected from Google's own Python base. The four modules worth knowing are flags, logging, app and testing.
Who is it for?
absl-py is worth taking when your program has named command line options, a test suite that needs a consistent base class, or a logging setup that already resembles the one you are about to write. It is not worth taking for a library or a service, because the dependency costs you something on every interpreter upgrade: v2.4.0 dropped Python 3.8 and 3.9 and pinned the package to 3.10 or newer, which is a floor you cannot ignore if you still support older runtimes.
Can I use it commercially?
Yes. Apache-2.0 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 12 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 September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Four modules, and the README names them without explaining them

The README's feature list is four lines long: simple application startup, a distributed commandline flags system, a custom logging module with additional features, and testing utilities. That is the entire marketing surface, and for a package with roughly 2,450 stars and a decade of production use behind it, four lines is about right.

Those four lines map onto the `absl/` package. `absl.flags` is the largest and most opinionated piece, and it deserves attention on its own later in this article. `absl.app` handles the entry point: it installs flags, parses argv, and calls `main`, which is why an Abseil program tends to have a very specific shape that looks a little like a Google internal binary. `absl.logging` is a wrapper over the standard library rather than a replacement for it, and the release notes for v2.5.0 make the direction explicit by updating type signatures so the module accepts the standard `logging` arguments `exc_info`, `stack_info`, `stacklevel` and `extra`.

That last change is the useful signal for an adopter. It says the module is being kept compatible with the standard library instead of drifting away from it, which matters because a logging wrapper that diverges is a logging wrapper you have to debug twice.

The fourth piece, testing, is `absltest`, and it is where the value shows up if you have written Python test suites in a large organisation before. `absltest.TestCase` is the base class the README points at indirectly through `smoke_tests/sample_app.py`, and v2.5.0 added `record_property` and `get_recorded_properties` methods to it, which is the kind of feature that exists because it was copied between internal codebases until someone published it.

Installing absl-py and getting a first program running

Installation is one line, and the README is not coy about it:

bash
pip install absl-py

From a checkout the same thing happens through pip, using the packaging metadata in `pyproject.toml`:

bash
pip install .

That file is worth reading before you install, because it states the constraints plainly. The build backend is hatchling, the package name is `absl-py` while the import name is `absl`, and `requires-python` is `>=3.10`. Classifiers list 3.10, 3.11, 3.12, 3.13 and 3.14. The version is not hardcoded in the packaging file: `[tool.hatch.version]` reads the path `absl/__init__.py`, so the version lives with the code rather than in the build config.

The first program to look at is named in the README itself, `smoke_tests/sample_app.py`, and the `smoke_tests/` directory at the repository root is the only place in the tree where an example lives. There is no `examples/` directory and no tutorial directory, which is unusual for a library this widely used and is a fair signal about how this project expects to be learned: through the developer guide rather than through worked examples in the repository.

Running the tests is a Bazel operation, not a pip one, and that has a practical consequence if you were planning to run them with pytest:

bash
git clone https://github.com/abseil/abseil-py.git
cd abseil-py
bazel test absl/...

The tree contains both `WORKSPACE` and `MODULE.bazel`, plus a pinned `.bazelversion`. v2.4.0 notes that the Bazel setup was modernized with `MODULE.bazel`, and the 2026-01-28 release also allowed `$PYTHONBREAKPOINT` to affect `runcall` and `post_mortem` debugging, which is a small but telling detail about who uses these modules.

The flags system replaces argparse rather than wrapping it

Abseil flags is the module with the most opinions and the most consequences, and it is worth understanding before you adopt anything else from the package. It defines flags at module level as module attributes, parsing happens once at startup, and the values live in a global registry that any function can read. That design is fast and it is the reason a large Google codebase can have thousands of flags, but it is a different model from argparse's namespace passed down through `main`.

The releases show the system being tightened rather than extended. v2.5.0, published on 2026-07-03, introduced a built-in flag called `--only_check_flags` that validates flag definitions without executing `main()`. That is a testing tool as much as a runtime one: it lets a test assert that a program's flags are internally consistent without letting the program start. The same release applied defensive copying in `save_flag_values` to stop dictionary mutation flakiness, and reworked the `DuplicateFlagError` message, which is the kind of fix that only matters once you have a large enough program to hit it.

v2.4.0 fixed a related bug that would bite anyone reloading modules: a duplicate flag definition when reloading a module. The change record also notes that the internals of `absl.flags.get_help_width()` were changed, which is a small warning that help output is not a stable interface.

There is a second flags tool here worth knowing about. `@flagsaver.flagsaver` saves and restores flag values around a block of code, and v2.5.0 added support for `async` test functions in it. If you adopt Abseil flags in a test-heavy codebase, flagsaver is the piece that makes flag mutation safe, and the changelog shows it maturing alongside the async ecosystem.

Debugging, profiling and the ModuleNotFoundError that greets newcomers

One of the higher-volume related searches for this package is the error `ModuleNotFoundError: No module named 'absl`, which tells you something real about the adoption path. Abseil is usually present in a Python environment as a transitive dependency of something larger, and the import name `absl` does not match the distribution name `absl-py`. That gap is exactly the kind of thing that sends people looking.

The debugging surface is in the `app` module rather than a separate tool. The release notes name `runcall` and `post_mortem` as the entry points, and v2.4.0 made them respect `$PYTHONBREAKPOINT`, so setting that environment variable in a test now drops you into a debugger where previously the setting was ignored. For anyone who has wanted to inspect an Abseil program mid-run and been mildly frustrated by it, that is the change to know about.

v2.5.0 added an `ABSL_PYTHON_PROFILE_FILE` environment variable for enabling Python profiling, which is a deliberate choice: the output goes to a file rather than to standard output, so profiling a batch job does not interleave with your logs. The same release expanded the use of `FlagHolder` objects across `app` and `absltest`, which is a cleanup with a purpose, since a holder gives you a typed, explicit way to carry a set of flag values into code that would otherwise reach into globals.

None of this is in the README. That is the recurring theme: the four-line feature list is accurate but the operational knowledge lives in the changelog, and reading `CHANGELOG.md` is a more efficient way to understand the library than the README is.

Type annotations are checked, and the release notes track that work

The README asks contributors to validate annotations against the latest mypy, and gives the command:

bash
pip install mypy
mypy absl

The project treats this as part of the definition of done rather than an optional extra, which is the clearest quality signal available for a library whose whole purpose is to be a dependency of other people's code. v2.5.0 lists fixing type annotations and compatibility with both MyPy and Pyrefly, and v2.4.0 records a correction to the type signature of `absltest.skipThisClass`. Two separate type checkers being named in one release note is a small but real signal of how seriously the annotations are taken.

The same v2.4.0 release modernized the annotations using Python 3.10 or newer features, which is the practical cost of that work: the annotation syntax itself now assumes a modern interpreter. Combined with dropping 3.8 and 3.9 and setting `requires-python` to `>=3.10`, the direction of travel is unambiguous.

Build and test infrastructure sits alongside the code rather than beside it. The tree has `BUILD.bazel`, `MODULE.bazel`, `WORKSPACE`, a pinned `.bazelversion`, a `ci/` directory, `docs/` with its own `.readthedocs.yaml`, and `CHANGELOG.md`, `CONTRIBUTING.md` and `AUTHORS` at the root. The hatchling configuration excludes `**/BUILD` and `**/tests` from both the wheel and the sdist, which is the right call: package consumers get the library, and the Bazel per-target definitions stay in the checkout.

What the repository settles, and what the developer guide has to answer

The split is sharp here, and in a useful way. The README tells you what the libraries are for, how to install them, how to run the tests, and which file to read first. Everything else is at abseil.io, under the Abseil Python Developer Guide, and that guide is where a real adoption decision gets made.

The README's Future Releases section is the sentence a buyer should weigh most carefully: the repository includes an initial set of libraries for early adoption, and more components plus interoperability with the Abseil C++ common libraries will come in future releases. That is an honest statement that the Python side is still filling out, and it also flags the most interesting direction, which is shared conventions across the C++ and Python libraries rather than a third implementation.

Against a direct alternative, the comparison is mostly about what you give up. If you write flags for one program, argparse or `click` is smaller and needs no global registry. If you need test helpers, `unittest` and `pytest` already give you a base class and fixtures, and `absltest` is a layer on top rather than a replacement. The case for Abseil is scale and consistency: many flags, many binaries, one house style, and a base class that behaves the same across repositories. The case against it is the same scale problem seen from the other side, where a small tool now inherits four libraries and a 3.10 floor.

Activity is not in question. The last recorded push to `main` was on 2026-09-25, and three releases in the recent history, v2.3.1 in July 2025, v2.4.0 in January 2026 and v2.5.0 in July 2026, follow a steady roughly six month cadence. The licence is Apache-2.0, the same terms as the C++ libraries, so there is no licensing asymmetry if you already ship Abseil-derived code.

Editorial conclusion

absl-py is worth taking when your program has named command line options, a test suite that needs a consistent base class, or a logging setup that already resembles the one you are about to write. It is not worth taking for a library or a service, because the dependency costs you something on every interpreter upgrade: v2.4.0 dropped Python 3.8 and 3.9 and pinned the package to 3.10 or newer, which is a floor you cannot ignore if you still support older runtimes. The flags system is the piece that carries the most weight, and it is also the piece most likely to surprise you, since it replaces argparse rather than wrapping it. Start with `smoke_tests/sample_app.py` in the repository, then read the Abseil Python Developer Guide on abseil.io, which covers considerably more than the README does.

Frequently asked questions

How do I install absl-py and run the example?

The README gives two install paths, `pip install absl-py` for the published package and `pip install .` from a checkout. The example it points at is `smoke_tests/sample_app.py`, which is the only example file in the repository tree. The package metadata in `pyproject.toml` requires Python 3.10 or newer and reads the version from `absl/__init__.py`.

How do I run the tests for abseil-py?

With Bazel, from a clone of the repository: `git clone https://github.com/abseil/abseil-py.git`, change into `abseil-py`, then `bazel test absl/...`. The repository carries both `WORKSPACE` and `MODULE.bazel` plus a pinned `.bazelversion`, and v2.4.0 records the move to the newer `MODULE.bazel` setup. Type annotations are checked separately with `mypy absl`.

What changed in the recent absl-py releases?

v2.5.0, published on 2026-07-03, added an `ABSL_PYTHON_PROFILE_FILE` environment variable, a `--only_check_flags` built-in flag, async support in `@flagsaver.flagsaver`, and `record_property` methods on `absltest.TestCase`. v2.4.0 added Python 3.14 support, dropped Python 3.8 and 3.9, and fixed a duplicate flag definition when reloading a module.

Should a small project depend on absl-py?

Probably not if the program has a handful of command line options. argparse or a library such as click is smaller, needs no global flag registry, and does not impose a Python 3.10 floor. absl-py earns its dependency when a codebase has many flags, many binaries and a shared test style, which is the situation the README describes as code collected from Google's own Python base.

Official sources

  1. abseil/abseil-py on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/abseil-abseil-py.svg)](https://hysenlabs.com/projects/abseil-abseil-py)