I am pleased to announce the release of pybind11 2.6.0! This is the largest release since 2.2 (released over three years ago). I would like to highlight some of the key changes below; be sure to check out the changelog and upgrade guide for more information! The focus of this release was stability, packaging, and supporting more platforms, though there are a lot of small features and useful additions, covered by newly expanded docs.
One of the headline features is a brand new CI system, testing over 50 different
configurations. This has enabled expanded support for compilers, such as NVCC,
PGI, and lots of versions of Clang, GCC, and MSVC, now tested from C++11 to (the
newly supported) C++20. Many warnings and bugs were fixed across the spectrum.
PyPy support has been updated to the 7.3.x series, and fully supports
for the first time. New Python 3.9 support includes a workaround for a segfault
in CPython 3.9.0 (pybind11 developers have fixed the bug in CPython, and 3.9.1
will work with older versions of pybind11 too; conda-forge also provides the
patch). every configuration supported by cibuildwheel is supported.
CMake build system
Another headline feature is the completely reworked build systems; first we will cover CMake. The focus was to support more situations and modern CMake tools in a backward compatible way, while maintaining support for CMake 3.4+. Most significantly, the generated Config/Target files now no longer depend on the generator platform, allowing a configuration to be used on a different machine. This enables, for the first time, the CMake files to be distributed in the Python package available on PyPI via pip!
You now simply use
CMAKE_CXX_STANDARD or compile features - pybind11 will
automatically require at least C++11 via compile features. You can use
pybind11 will get out of the way and let CMake dictate those features.
a language is fully supported now. And the Python discovery is much smarter,
finding virtual environments and conda.
A huge new feature is support for CMake’s modern FindPython tooling; you can now simply write:
find_package(Python COMPONENTS Interpreter Development)
and pybind11 will respect the Python you found, and will use the new variables.
You can force the new search by instead setting
PYBIND11_FINDPYTHON ON before
including pybind11. This does requires CMake 3.12, with 3.15+ better and 3.18.2+
best, especially for PyPy (you also should use PyPy 7.3.2+).
You can now disable Python discovery entirely by setting
PYBIND11_NOPYTHON TRUE, and then do it yourself with the modular targets
provided. This is ideal for working in a large existing framework, or using
Scikit-build’s helper file.
There is much more to explore, as well, like finer-grained targets and new helper functions.
Not to be outdone, the setuptools packaging has been completely reworked and
expanded to better support both simple and advanced setuptools projects. Before
2.6.0, pybind11 extensions that wanted to be widely available and avoid
requiring CMake had to follow the python example repo. The basic ideas in
that repo have now been integrated into a
pybind11.setup_helpers module, and
can be used any way that you would like to use pybind11. A lot of long-standing
issues with the example have been fixed; if you have ever seen a setup.py with
the (incorrect) statement that “
has_flag” is part of Python 3.6+, you know
that someone was copying this example. You can also be pretty sure that they
have an incorrect
has_flag function, as well, that will generate temporary
files in your working directory on Windows. These and other bugs have been fixed
setup_helpers; it properly supports Windows compilers, C++17, etc.
Using it is a breeze. Just use PEP 518’s
pyproject.toml file to list pybind11,
or if you use the submodule form instead, just do:
DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.join(DIR, "extern", "pybind11"))
from pybind11.setup_helpers import Pybind11Extension # noqa: E402
(better yet, use pathlib if you are Python 3 only). Building an extension is simple:
ext_modules = [
extra_compile_args=["/d2FH4-"] if sys.platform.startswith("win32") else ,
This looks just like a standard Extension (and is a subclass of it), but will
set up the flags needed to compile pybind11 extensions. It also has a
setting that selects a C++ standard to use. There is also a
argument that can disable the inclusion of the pybind11 directory (the
setup_helpers file is completely standalone, and can even be copied into your
project or even your
Note that above I added a normal addition for an extension; the
extra_compile_args. All normal additions are supported. (If you are curious,
the one I illustrate above will keep extensions that are built on MSVC 2019 from
adding an extra runtime dependency that some older redistributable downloads do
If you want to leave off the
cxx_std and instead use the highest available
standard, then you need to also add the
(currently, that is all this does, though in the future more functionality could
be added, like MinGW support):
from pybind11.setup_helpers import build_ext
There is also a parallel compiler utility, which can dramatically speed up the compile performance of your extension on multicore hardware:
from pybind11.setup_helpers import ParallelCompile
The variable name you choose when constructing it allows users to control the number of threads (the one here matches NumPy, which has similar functionality). You can also control the default and max number of threads via keyword arguments.
Besides stability and bugfixes, and major building improvements, there are a significant collection of exciting new features.
Keyword-only and positional-only arguments are now supported on any version of Python. Use them like this:
.def("my_func", &func, "p1"_a, py::pos_only(), "n1"_a, py::kw_only(), "k1"_a)
This will define a function with one positional only argument, a normal argument
n1, and a keyword-only argument
k1. This can help you design tight, clean
interfaces that are easy to maintain. A bug with
.none() has also been fixed
You can now use
py::is_final() to force a class to be uninheritable (CPython
only). You can use
py::prepend() to insert a function at the top of the call
stack instead of last. There’s also now a way to get the type object from a
registered C++ type with
py::type::of<T>(), or you can get the type from a
Python object with
Support for code correctness
In several ways, pybind11 now helps you write more correct code. If you forget
__init__ on a pybind11 class, an error is thrown (since the C++ memory
is not initialized correctly without it). Conversions to python types, like
py::bytes from general types like
py::object now throw if the conversion is
invalid, rather than having to check
Lots of small changes were made to better support C++20 or be clearer/cleaner. There no longer is a nested submodule in the repo (great for use as a submodule from other places, like GitLab). Check out the full list, there are bugs finally fixed after several years in some cases! The docs have also been expanded and feature several new pages and sections.
New maintainer team
The largest change might not be in the code at all. A new collection of some of the best contributors were pulled in and made part of the maintenance team. There are more than a half-dozen of us, and we cover a wide range of backgrounds and interests, from High Energy Physics to Google. We would also like to thank Google for a generous donation to help our large number of CI jobs to run fully in parallel.
There are more exciting improvements to come! Hopefully releases will be a little more regular in the future with more patch releases and more frequent releases. Please continue to help us catch issues early by testing with the master branch! We can sometimes pull or change a feature on the master branch, but it should be quite stable, as it has to pass our 50+ checks.