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

MAINT: Escalate import warning to an import error #26149

Merged
merged 3 commits into from Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions doc/source/user/troubleshooting-importerror.rst
Expand Up @@ -183,6 +183,34 @@ that usually works is to upgrade the NumPy version::

pip install numpy --upgrade


Downstream ImportError or AttributeError
========================================

If you see a message such as::

A module that was compiled using NumPy 1.x cannot be run in
NumPy 2.0.0 as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.

Either as an ``ImportError`` or with::

AttributeError: _ARRAY_API not found

Then you are using NumPy 2 together with a module that was build with NumPy 1.
NumPy 2 made some changes that require rebuilding such modules to avoid
possibly incorrect results or crashes.

As the error message suggests, the easiest solution is likely to downgrade
NumPy to `numpy<2`.
Alternatively, you can search the traceback (from the back) to find the first
line that isn't inside NumPy to see which module needs to be updated.

NumPy 2 was released in the first half of 2024 and especially smaller
modules downstream are expected need time to adapt and publish a new version.


Segfaults or crashes
====================

Expand Down
44 changes: 14 additions & 30 deletions numpy/core/_multiarray_umath.py
Expand Up @@ -14,50 +14,34 @@ def __getattr__(attr_name):
from ._utils import _raise_warning

if attr_name in {"_ARRAY_API", "_UFUNC_API"}:
from numpy.version import short_version, release
from numpy.version import short_version
import textwrap
import traceback
import sys

msg = textwrap.dedent(f"""
A module that was compiled using NumPy 1.x cannot be run in
NumPy {short_version} as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled against NumPy 2.0.
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.

If you are a user of the module, the easiest solution will be to
either downgrade NumPy or update the failing module (if available).
downgrade to 'numpy<2' or try to upgrade the affected module.
We expect that some modules will need time to support NumPy 2.

""")
if not release and short_version.startswith("2.0.0"):
# TODO: Can remove this after the release.
msg += textwrap.dedent("""\
NOTE: When testing against pre-release versions of NumPy 2.0
or building nightly wheels for it, it is necessary to ensure
the NumPy pre-release is used at build time.
The main way to ensure this is using no build isolation
and installing dependencies manually with NumPy.

If your dependencies have the issue, check whether they
build nightly wheels build against NumPy 2.0.

pybind11 note: If you see this message and do not see
any errors raised, it's possible this is due to a
package using an old version of pybind11 that should be
updated.

""")
msg += "Traceback (most recent call last):"
tb_msg = "Traceback (most recent call last):"
for line in traceback.format_stack()[:-1]:
if "frozen importlib" in line:
continue
msg += line
# Only print the message. This has two reasons (for now!):
# 1. Old NumPy replaced the error here making it never actually show
# in practice, thus raising alone would not be helpful.
# 2. pybind11 simply reaches into NumPy internals and requires a
# new release that includes the fix. That is missing as of 2023-11.
# But, it "conveniently" ignores the ABI version.
sys.stderr.write(msg)
tb_msg += line

# Also print the message (with traceback). This is because old versions
# of NumPy unfortunately set up the import to replace (and hide) the
# error. The traceback shouldn't be needed, but e.g. pytest plugins
# seem to swallow it and we should be failing anyway...
sys.stderr.write(msg + tb_msg)
raise ImportError(msg)

ret = getattr(_multiarray_umath, attr_name, None)
if ret is None:
Expand Down