Skip to content

Commit f8d6296

Browse files
BUG: Improve ImportError message to suggest importing dependencies directly for full error details (#61084)
* Add hint to display full message for missing dependencies in pandas/init.py * ENH: Improve import error handling to preserve original traceback * TST: refactor testing for hard dependency package * Update pandas/__init__.py Co-authored-by: Matthew Roeschke <[email protected]> * Refactor prevent statement too long * ENH: change unittest to verify ImportError is raised when required dependencies are missing * TST: Use pytest.raises match parameter in test_missing_required_dependency --------- Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 07c627c commit f8d6296

File tree

2 files changed

+19
-40
lines changed

2 files changed

+19
-40
lines changed

pandas/__init__.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@
44

55
# Let users know if they're missing any of our hard dependencies
66
_hard_dependencies = ("numpy", "dateutil")
7-
_missing_dependencies = []
87

98
for _dependency in _hard_dependencies:
109
try:
1110
__import__(_dependency)
1211
except ImportError as _e: # pragma: no cover
13-
_missing_dependencies.append(f"{_dependency}: {_e}")
12+
raise ImportError(
13+
f"Unable to import required dependency {_dependency}. "
14+
"Please see the traceback for details."
15+
) from _e
1416

15-
if _missing_dependencies: # pragma: no cover
16-
raise ImportError(
17-
"Unable to import required dependencies:\n" + "\n".join(_missing_dependencies)
18-
)
19-
del _hard_dependencies, _dependency, _missing_dependencies
17+
del _hard_dependencies, _dependency
2018

2119
try:
2220
# numpy compat

pandas/tests/test_downstream.py

+14-33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import array
66
from functools import partial
7+
import importlib
78
import subprocess
89
import sys
910

@@ -186,41 +187,21 @@ def test_yaml_dump(df):
186187
tm.assert_frame_equal(df, loaded2)
187188

188189

189-
@pytest.mark.single_cpu
190-
def test_missing_required_dependency():
191-
# GH 23868
192-
# To ensure proper isolation, we pass these flags
193-
# -S : disable site-packages
194-
# -s : disable user site-packages
195-
# -E : disable PYTHON* env vars, especially PYTHONPATH
196-
# https://github.com/MacPython/pandas-wheels/pull/50
197-
198-
pyexe = sys.executable.replace("\\", "/")
199-
200-
# We skip this test if pandas is installed as a site package. We first
201-
# import the package normally and check the path to the module before
202-
# executing the test which imports pandas with site packages disabled.
203-
call = [pyexe, "-c", "import pandas;print(pandas.__file__)"]
204-
output = subprocess.check_output(call).decode()
205-
if "site-packages" in output:
206-
pytest.skip("pandas installed as site package")
207-
208-
# This test will fail if pandas is installed as a site package. The flags
209-
# prevent pandas being imported and the test will report Failed: DID NOT
210-
# RAISE <class 'subprocess.CalledProcessError'>
211-
call = [pyexe, "-sSE", "-c", "import pandas"]
212-
213-
msg = (
214-
rf"Command '\['{pyexe}', '-sSE', '-c', 'import pandas'\]' "
215-
"returned non-zero exit status 1."
216-
)
190+
@pytest.mark.parametrize("dependency", ["numpy", "dateutil"])
191+
def test_missing_required_dependency(monkeypatch, dependency):
192+
# GH#61030
193+
original_import = __import__
194+
mock_error = ImportError(f"Mock error for {dependency}")
195+
196+
def mock_import(name, *args, **kwargs):
197+
if name == dependency:
198+
raise mock_error
199+
return original_import(name, *args, **kwargs)
217200

218-
with pytest.raises(subprocess.CalledProcessError, match=msg) as exc:
219-
subprocess.check_output(call, stderr=subprocess.STDOUT)
201+
monkeypatch.setattr("builtins.__import__", mock_import)
220202

221-
output = exc.value.stdout.decode()
222-
for name in ["numpy", "dateutil"]:
223-
assert name in output
203+
with pytest.raises(ImportError, match=dependency):
204+
importlib.reload(importlib.import_module("pandas"))
224205

225206

226207
def test_frame_setitem_dask_array_into_new_col(request):

0 commit comments

Comments
 (0)