Skip to content

Build fails with free-threaded Python #21889

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

Open
2 tasks done
brianhelba opened this issue Mar 21, 2025 · 3 comments
Open
2 tasks done

Build fails with free-threaded Python #21889

brianhelba opened this issue Mar 21, 2025 · 3 comments
Assignees
Labels
accepted Ready for implementation bug Something isn't working P-medium Priority: medium python Related to Python Polars

Comments

@brianhelba
Copy link

brianhelba commented Mar 21, 2025

Checks

  • I have checked that this issue has not already been reported.
  • I have confirmed this bug exists on the latest version of Polars.

Issue description

When building polars against free-threaded Python 3.13.2 on Linux (using the nightly version of Rust), the build fails with the error:

         Compiling numpy v0.23.0
      error[E0432]: unresolved import `pyo3::sync::GILProtected`
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.23.0/src/datetime.rs:63:12
         |
      63 | use pyo3::{sync::GILProtected, Bound, Py, Python};
         |            ^^^^^^^^^^^^^^^^^^ no `GILProtected` in `sync`
         |
      note: found an item that was configured out
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.23.5/src/sync.rs:47:12
         |
      47 | pub struct GILProtected<T> {
         |            ^^^^^^^^^^^^
      note: the item is gated here
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.23.5/src/sync.rs:46:1
         |
      46 | #[cfg(not(Py_GIL_DISABLED))]
         | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

      error[E0432]: unresolved import `pyo3::sync::GILProtected`
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.23.0/src/strings.rs:15:5
         |
      15 |     sync::GILProtected,
         |     ^^^^^^^^^^^^^^^^^^ no `GILProtected` in `sync`
         |
         = note: unresolved item `crate::datetime::units::GILProtected` exists but is inaccessible
      note: found an item that was configured out
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.23.5/src/sync.rs:47:12
         |
      47 | pub struct GILProtected<T> {
         |            ^^^^^^^^^^^^
      note: the item is gated here
        --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.23.5/src/sync.rs:46:1
         |
      46 | #[cfg(not(Py_GIL_DISABLED))]
         | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

      error[E0282]: type annotations needed for `&mut _`
         --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.23.0/src/datetime.rs:229:13
          |
      229 |         let dtype = match dtypes.get_or_insert_with(Default::default).entry(unit) {
          |             ^^^^^
      ...
      247 |         dtype.bind(py).to_owned()
          |               ---- type must be known at this point
          |
      help: consider giving `dtype` an explicit type, where the type for type parameter `V` is specified
          |
      229 |         let dtype: &mut V = match dtypes.get_or_insert_with(Default::default).entry(unit) {
          |                  ++++++++

      error[E0282]: type annotations needed for `&mut _`
         --> /.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.23.0/src/strings.rs:185:13
          |
      185 |         let dtype = match dtypes.get_or_insert_with(Default::default).entry(size) {
          |             ^^^^^
      ...
      198 |         dtype.bind(py).to_owned()
          |               ---- type must be known at this point
          |
      help: consider giving `dtype` an explicit type, where the type for type parameter `V` is specified
          |
      185 |         let dtype: &mut V = match dtypes.get_or_insert_with(Default::default).entry(size) {
          |                  ++++++++

      Some errors have detailed explanations: E0282, E0432.
      For more information about an error, try `rustc --explain E0282`.
      error: could not compile `numpy` (lib) due to 4 previous errors
      warning: build failed, waiting for other jobs to finish...
      💥 maturin failed
        Caused by: Failed to build a native library through cargo
        Caused by: Cargo build finished with "exit status: 101": `env -u CARGO PYO3_ENVIRONMENT_SIGNATURE="cpython-3.13-64bit" PYO3_PYTHON="/.../.cache/uv/builds-v0/.tmpV8LOZL/bin/python"
      PYTHON_SYS_EXECUTABLE="/.../.cache/uv/builds-v0/.tmpV8LOZL/bin/python" "cargo" "rustc" "--message-format" "json-render-diagnostics" "--manifest-path" "/.../.cache/uv/sdists-v8/pypi/polars/1.25.2/ItmSIH_8XlFqKYzSiXKdr/src/py-polars/Cargo.toml"
      "--release" "--lib"`
      Error: command ['maturin', 'pep517', 'build-wheel', '-i', '/.../.cache/uv/builds-v0/.tmpV8LOZL/bin/python', '--compatibility', 'off'] returned non-zero exit status 1

This error has already been solved upstream by PyO3/rust-numpy#471 and released in rust-numpy 0.24.

To resolve this, I believe that at least polars needs to upgrade the Rust dependency numpy to 0.24 (and likely pyo3 to 0.24 too). Other fixes may be necessary too.

This upgrade work may be related to the PRs #20111 and #20683 by @bschoenmaeckers .

@brianhelba brianhelba added bug Something isn't working needs triage Awaiting prioritization by a maintainer python Related to Python Polars labels Mar 21, 2025
@bschoenmaeckers
Copy link
Contributor

bschoenmaeckers commented Mar 21, 2025

It is currently not possible to upgrade to the latest PyO3 release because of a upstream bug. I will pick this up when ready. Free-threading probably requires more internal changes to prevent deadlocks.

@orlp orlp added accepted Ready for implementation P-medium Priority: medium and removed needs triage Awaiting prioritization by a maintainer labels Mar 21, 2025
@bschoenmaeckers
Copy link
Contributor

bschoenmaeckers commented Mar 25, 2025

I did some testing in #21914 and the main blockers in our dependency tree are:

After this we should be able to do some testing in the CI to make sure polars is thread-safe.

@Object905
Copy link
Contributor

Note that greenlet is only a dependency of gevent and it's not used directly.
Also given how they're maintained (not abandoned, but mostly catching up with upstream python) and how they work (by exploiting python internals and swapping stacks) I doubt that we will see them support free-threaded in foreseeable future.

Also they're used only for collect_async (which are marked experimental) as an alternative mode to asyncio, that I made, because I needed that for a legacy project, that since migrated to not using gevent 😃
My point is while they're default libraries for green threading - green threading in general is not a popular choice in python nowadays and my feeling that you can count users that use polars+gevent+collect_async on one hand (if there are any).
So, removing gevent support in collect_async altogether should be fine?

But seems like they shouldn't block free-threaded builds, because its an optional dependency and you couldn't build/use them in free-threaded anyway. But they're have to be excluded from requirements/tests in free-threaded in CI.

ref
python-greenlet/greenlet#423
gevent/gevent#2087

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted Ready for implementation bug Something isn't working P-medium Priority: medium python Related to Python Polars
Projects
None yet
Development

No branches or pull requests

4 participants