diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 4018418294963..8fd9f07442810 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -82,7 +82,7 @@ Other Enhancements - :meth:`DataFrame.query` and :meth:`DataFrame.eval` now supports quoting column names with backticks to refer to names with spaces (:issue:`6508`) - :func:`merge_asof` now gives a more clear error message when merge keys are categoricals that are not equal (:issue:`26136`) - :meth:`pandas.core.window.Rolling` supports exponential (or Poisson) window type (:issue:`21303`) -- +- Error message for missing required imports now includes the original ImportError's text (:issue:`23868`) .. _whatsnew_0250.api_breaking: diff --git a/pandas/__init__.py b/pandas/__init__.py index 4c494b4a62e39..11ea3047bb62a 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -10,11 +10,13 @@ try: __import__(dependency) except ImportError as e: - missing_dependencies.append(dependency) + missing_dependencies.append((dependency, e)) if missing_dependencies: - raise ImportError( - "Missing required dependencies {0}".format(missing_dependencies)) + msg = "Unable to import required dependencies:" + for dependency, e in missing_dependencies: + msg += "\n{0}: {1}".format(dependency, str(e)) + raise ImportError(msg) del hard_dependencies, dependency, missing_dependencies # numpy compat diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py index 3b4f85e680f6e..f8319999682e8 100644 --- a/pandas/tests/test_base.py +++ b/pandas/tests/test_base.py @@ -1,7 +1,9 @@ from datetime import datetime, timedelta +from importlib import reload from io import StringIO import re import sys +from unittest.mock import patch import numpy as np import pytest @@ -1341,3 +1343,28 @@ def test_to_numpy_dtype(as_series): expected = np.array(['2000-01-01T05', '2001-01-01T05'], dtype='M8[ns]') tm.assert_numpy_array_equal(result, expected) + + +@patch("builtins.__import__") +def test_missing_required_dependency(mock_import): + def mock_import_fail(name, *args, **kwargs): + if name == "numpy": + raise ImportError("cannot import name numpy") + elif name == "pytz": + raise ImportError("cannot import name some_dependency") + elif name == "dateutil": + raise ImportError("cannot import name some_other_dependency") + else: + return __import__(name, *args, **kwargs) + + mock_import.side_effect = mock_import_fail + + expected_msg = ( + "Unable to import required dependencies:" + "\nnumpy: cannot import name numpy" + "\npytz: cannot import name some_dependency" + "\ndateutil: cannot import name some_other_dependency" + ) + + with pytest.raises(ImportError, match=expected_msg): + reload(pd)