Python 3.15.0rc1 on conda-forge, a leaner libpython, and a more unixy Windows layout
Following the release of Python 3.15.0rc1, conda-forge has started building Python 3.15 packages. You can create an environment with the Python 3.15 release candidate by running the command:
conda create -n py315 python=3.15 -c conda-forge -c conda-forge/label/python_rc
As with previous feature releases, we start building against the release
candidate because the ABI is guaranteed to be stable from here to the final
3.15.0. This is also a release where the python package on Windows looks
noticeably different on disk, and where the shared library that every
python package used to carry has moved into its own package.
Note that at this early stage only the python interpreter itself, noarch
packages, and extensions built against the stable ABI (abi3) are available
for 3.15. The broader rebuild of compiled packages hasn't started yet — that
begins once a python315 entry lands in conda-forge-pinning,
the same way it did for 3.14 and 3.13.
That initial migration will only cover the regular (non-freethreading)
builds — the 3.14t migration keeps running in the meantime, and a 3.15t
migration will start at a later date, the same way 3.14t followed 3.13t
(conda-forge/conda-forge-pinning-feedstock#8891).
A more unixy layout on Windows
For as long as conda-forge has shipped Python on Windows, the layout inside
an environment has looked like a regular Windows Python install: a flat
Lib\ for the standard library and site-packages, a top-level DLLs\ for
compiled extension modules, include\ for headers, and libs\ for import
libraries. On Unix, the same content is grouped under a single
lib/pythonX.Y/ tree. That divergence meant every other package uses
<PREFIX>\Library\ instead of <PREFIX>\ on windows.
Starting with 3.15, conda-forge's Windows builds move to a layout that mirrors the Unix one:
| content | old path (≤3.14) | new path (3.15+) |
|---|---|---|
| standard library | Lib\ | lib\python\ |
| site-packages | Lib\site-packages\ | lib\python\site-packages\ |
compiled extension modules (.pyd) | DLLs\ | lib\python\lib-dynload\ |
Tools\ scripts | Tools\ | lib\python\Tools\ |
headers, pyconfig.h | include\ | include\python\ |
Scripts\, libs\, and the top-level python.exe/pythonw.exe/python3.dll are
unchanged. This is purely about conda-forge's own Python build layout — it
doesn't touch the general Library\ convention that other conda packages
use for their headers and DLLs on Windows.
This will help to remove the distinction between <PREFIX>/Library
and <PREFIX> in the future, but we will keep the distinction for now.
See conda-forge/python-feedstock#873 for the change and CFEP-27 for the CFEP that explains the rationale.
The shared library moves into its own libpython package
The python package has always carried the shared library —
libpythonX.Y.so/.dylib even though most environments never touch
it directly. It's only needed for apps that embed python. This is because
on Unix, the python executable links against the static libpython library
for performance reasons. Every other package that just runs Python or uses
compiled extensions was paying for bytes it didn't use.
conda-forge already split the static archive out into libpython-static
some time ago. For 3.15, the shared library gets the same treatment: a new
libpython output now carries it, and python is simply run_constrained by
an exact pin of libpython. Installing python now doesn't give you the
shared library and applications that embed python need to depend on
libpython directly, and environments that don't need it can end up
smaller. This work
started on the 3.15 branch and will be backported to previous minor
versions, but installing python on those versions will bring in libpython
automatically unlike 3.15.
Alongside this, macOS now also gets an unversioned libpython3.dylib for
stable-ABI (abi3) consumers, matching the libpython3.so that has long
existed on Linux for the same purpose — so applications that embed Python
via the stable ABI on macOS no longer need to pin an exact Python minor
version to link against. This is distinct from regular Python extension
modules built against abi3, which don't link against libpython at all.
Note that libpython is empty on windows, and python*.dll are in the python
package since the executables depend on the shared library unlike Unix.
Also note that the libpython name was previously used by a Windows-only
package from libpython-feedstock
that provided a mingw-w64 import library for pythonXY.dll, for use with
the m2 (mingw) toolchain. That old meaning has been repurposed to make room
for the new libpython output described above — anyone who depended on it
for the m2 toolchain should switch to distutils-activate-mingw instead
(conda-forge/libpython-feedstock#20).
See conda-forge/python-feedstock#843 for the motivation and #894 and #885 for the implementation across platforms.
Dropping the old python3.1 symlink
conda-forge's Python builds have long carried a python3.1 symlink (and a
matching site-packages path) alongside the real interpreter, as a
workaround for an old bug in conda (conda/conda#10969)
where minor versions with two digits, like 3.10 or 3.15, could be
misparsed as 3.1. That bug has long since been fixed, and 3.15 drops the
python3.1 symlink and the associated workaround
(conda-forge/python-feedstock#912).
Thanks
Thanks to Michał Górny (@mgorny) for the 3.15.0rc1
bump and the original libpython split, and to Axel Obermeier
(@h-vetinari) for backporting the libpython PRs
to previous versions.
Some of this work was partially funded by Sovereign Tech Agency
Any issues with the python package itself can be reported at
python-feedstock.
