Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide downloadable free-threaded macOS builds for Python 3.13 #120098

Open
ned-deily opened this issue Jun 5, 2024 · 5 comments
Open

Provide downloadable free-threaded macOS builds for Python 3.13 #120098

ned-deily opened this issue Jun 5, 2024 · 5 comments

Comments

@ned-deily
Copy link
Member

ned-deily commented Jun 5, 2024

[NOTE: This issue is specifically about the python.org macOS installer for 3.13.0 beta 2 and later and how to use it. If you have issues with the free-threading feature itself (not the installation of it on macOS), please search Python Discuss and this CPython issue tracker first and comment or create issues there. Thanks!]

The CPython release team provides various binaries of Python with each feature and bug-fix release for various platforms, currently Windows and macOS. As has been discussed elsewhere (for example, #112430), there is a strong desire within the community for the release team to also provide additional free-threaded builds in support of the PEP 703 free-threaded ("no GIL") feature currently in beta-testing for Python 3.13.

Since this feature is still labeled as experimental, there will likely be issues and updates that arise as it gets more exposure during the remainder of the 3.13 release cycle. Likewise, supporting packaging and releasing of two separate interpreter binaries, a traditional ("GIL-only") one and the experimental free-threaded ("GIL-optional"), raises new issues, as well. This issue is meant to serve as a meta-issue for free-threading support in the pre-built macOS binaries provided for macOS on python.org by the release team. (Windows support is described here.) 3.13 release notices and the documentation (readme's) included with the downloadables for macOS will refer you to this issue to find the latest information.

The initial python.org download for free-threaded macOS binaries is included in the 3.13.0 beta 2 release.

@ned-deily
Copy link
Member Author

From the 3.13.0b2 macOS installer ReadMe file, which is displayed during installation and available after installation in /Applications/Python 3.13/ReadMe.rtf:

Free-threading support

NEW as of 3.13.0b2: This installer package can now optionally install an additional build of Python 3.13 that supports the experimental free-threading feature (running with the global interpreter lock disabled).

See the release notice, the 3.13 What's New document, and issue #120098 [this issue] for more information.

Because this feature is still considered experimental, the support for it is not installed by default. It is packaged as a separate install option, available by clicking the Customize button on the Installation Type step of the installer as described above. When selected, a separate PythonT.framework will also be installed alongside the normal Python.framework in /Library/Frameworks. This configuration allows a free-threaded Python 3.13 build to co-exist on your system with a traditional (GIL only) Python 3.13 build with minimal risk while installing or testing. This installation layout is itself experimental and is subject to change prior to the release of Python 3.13.0.

Known cautions and limitations as of 3.13.0b2:

  • The Free-threaded Python package is not installed by default. To select it, click on the Customize button in the Installation Type panel during the install and then click to select the Free-Threaded Python package.

  • The UNIX command-line tools package, which is selected by default, will install links in /usr/local/bin for python3.13t, the free-threaded interpreter, and python3.13t-config, a configuration utility which may be useful for package builders. Since /usr/local/bin is typically included in your shell PATH, in most cases no changes to your PATH environment variables should be needed to use python3.13t.

  • For this release, the Shell profile updater package and the Update Shell Profile.command in /Applications/Python 3.13 do not support the free-threaded package.

  • When working with multiple Python environments, it is usually safest and easiest to create and use virtual environments. This can avoid possible command name conflicts and confusion about which Python is in use:
    python3.13t -m venv directory_name
    then activate.

  • To install a separate instance of pip for use with the free-threaded Python:
    python3.13t -m ensurepip --upgrade

  • To install a package using pip without a venv:
    python3.13t -m pip install _package_name_

  • To run a free-threaded version of IDLE:
    python3.13t -m idlelib

  • The free-threaded build and the traditional build have separate search paths and separate site-packages directories so, by default, if you need a package available in both builds, it may need to be installed in both.

  • The interpreters in both builds respond to the same PYTHON environment variables which may have unexpected results, for example, if you have one, like PYTHONPATH, set in a shell profile. If necessary, there are command line options like -E to ignore these environment variables.

  • The free-threaded build links to the third-party shared libraries, such as OpenSSL and Tk, installed in the traditional framework. This means that both builds also share one set of trust certificates as installed by the Install Certificates command script.

@ned-deily
Copy link
Member Author

ned-deily commented Jun 5, 2024

If you want to use automation to install the free-threaded interpreter (rather than by using the familiar macOS Installer GUI app), the macOS command line installer utility lets you select non-default options, too. If you are not familiar with installer, it can be somewhat cryptic (see man installer for more info). The following shell snippet shows one way to do it:

RELEASE="python-3.13.0b2-macos11.pkg"

# download installer pkg
curl -O https://www.python.org/ftp/python/3.13.0/${RELEASE}

# create installer choicechanges to customize the install:
#    enable the PythonTFramework-3.13 package
#    while accepting the other defaults (install all other packages)
cat > ./choicechanges.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
        <dict>
                <key>attributeSetting</key>
                <integer>1</integer>
                <key>choiceAttribute</key>
                <string>selected</string>
                <key>choiceIdentifier</key>
                <string>org.python.Python.PythonTFramework-3.13</string>
        </dict>
</array>
</plist>
EOF

sudo installer -pkg ./${RELEASE} -applyChoiceChangesXML ./choicechanges.plist -target /

You can then test that both installer builds are now available with something like:

$ # test that the free-threaded interpreter was installed if the Unix Command Tools package was enabled
$ /usr/local/bin/python3.13t -VV
Python 3.13.0b2 experimental free-threading build (v3.13.0b2:3a83b172af, Jun  5 2024, 12:57:31) [Clang 15.0.0 (clang-1500.3.9.4)]
$ #    and the traditional interpreter
$ /usr/local/bin/python3.13 -VV
Python 3.13.0b2 (v3.13.0b2:3a83b172af, Jun  5 2024, 12:50:24) [Clang 15.0.0 (clang-1500.3.9.4)]
$ # test that they are also available without the prefix if /usr/local/bin is on $PATH
$ python3.13t -VV
Python 3.13.0b2 experimental free-threading build (v3.13.0b2:3a83b172af, Jun  5 2024, 12:57:31) [Clang 15.0.0 (clang-1500.3.9.4)]
$ python3.13 -VV
Python 3.13.0b2 (v3.13.0b2:3a83b172af, Jun  5 2024, 12:50:24) [Clang 15.0.0 (clang-1500.3.9.4)]
@ned-deily
Copy link
Member Author

ned-deily commented Jun 6, 2024

If you cannot depend on the link in /usr/local/bin pointing to the python.org free-threaded python3.13t (for example, if you want to install your own version there or some other distribution does), you can explicitly set your shell PATH environment variable to include the PythonT framework bin directory:

export PATH="/Library/Frameworks/PythonT.framework/Versions/3.13/bin":"$PATH"

The traditional framework installation by default does something similar, except for Python.framework. Be aware that having both framework bin directories in PATH can lead to confusion if there are duplicate names like python3.13 in both; which is actually used depends on the order they appear in PATH. The which python3.13 or which python3.13t commands can show which path is being used. Using virtual environments can help avoid such ambiguities. Another option might be to create shell alias's to the desired interpreters, like:

alias python3.13="/Library/Frameworks/Python.framework/Versions/3.13/bin/python3.13"
alias python3.13t="/Library/Frameworks/PythonT.framework/Versions/3.13/bin/python3.13t"
@ronaldoussoren
Copy link
Contributor

Two small issues I ran into:

  1. The PythonT framework's bin directory contains both python3.13t and python3.13 which makes it easier to accidentally invoke the wrong variant when both the PythonT and Python frameworks are on $PATH:
% ls /Library/Frameworks/PythonT.framework/Versions/3.13/bin                                                                                      python3.13		python3.13t		python3.13t-config
  1. The Install Certificates.command only installs certifi for the classic build and not for the free threaded one.

The latter might also be true for the installer action that installs pip, although that may also be user error and I haven't tried to reproduce this yet. I installed both pip and certifi manually for the free-threaded build.

@nineteendo
Copy link
Contributor

Would you prefer them to be removed?

cpython/Makefile.pre.in

Lines 2197 to 2202 in 6af190f

-if test "$(VERSION)" != "$(LDVERSION)"; then \
if test -f $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE) -o -h $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE); \
then rm -f $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE); \
fi; \
(cd $(DESTDIR)$(BINDIR); $(LN) python$(LDVERSION)$(EXE) python$(VERSION)$(EXE)); \
fi

cpython/Makefile.pre.in

Lines 2258 to 2270 in c2d810b

-if test -f $(DESTDIR)$(BINDIR)/python3$(EXE) -o -h $(DESTDIR)$(BINDIR)/python3$(EXE); \
then rm -f $(DESTDIR)$(BINDIR)/python3$(EXE); \
else true; \
fi
(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python3$(EXE))
-if test "$(VERSION)" != "$(LDVERSION)"; then \
rm -f $(DESTDIR)$(BINDIR)/python$(VERSION)-config; \
(cd $(DESTDIR)$(BINDIR); $(LN) -s python$(LDVERSION)-config python$(VERSION)-config); \
rm -f $(DESTDIR)$(LIBPC)/python-$(VERSION).pc; \
(cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(LDVERSION).pc python-$(VERSION).pc); \
rm -f $(DESTDIR)$(LIBPC)/python-$(VERSION)-embed.pc; \
(cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(LDVERSION)-embed.pc python-$(VERSION)-embed.pc); \
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment