Skip to content

Commit debb36e

Browse files
committed
Add guide on how to handle missing extras
1 parent 363e4a6 commit debb36e

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
.. _handling-missing-extras-at-runtime:
2+
3+
============================================================
4+
Handling missing optional dependencies ("extras") at runtime
5+
============================================================
6+
7+
If your package has :ref:`optional dependencies ("extras")
8+
<metadata_provides_extra>` which the package consumer hasn't installed, the
9+
default outcome is an ordinary `ModuleNotFoundError` exception being raised at
10+
the first attempted import of a missing module.
11+
12+
This can make for a bad user experience, because there is no guidance about why
13+
the module is missing - users might think they've found a bug. If you're not
14+
careful, it can even make your package unusable without the extras installed,
15+
e.g. if your package is a library that imports the affected modules from the
16+
top-level module or from the application entry point if it's an application.
17+
18+
As of the time of writing, there is no *great* way to handle this issue in
19+
the Python packaging ecosystem, but there are a few options that might be
20+
better than nothing:
21+
22+
23+
Overall approach
24+
================
25+
26+
TODO General guidance about how to isolate imports in question
27+
28+
TODO Optimistic vs pessimistic handling?
29+
30+
31+
Handling failing imports
32+
========================
33+
34+
TODO example
35+
36+
TODO mention it doesn't check versions, so a bit dangerous
37+
38+
39+
Using ``pkg_resources``
40+
=======================
41+
42+
The now-deprecated ``pkg_resources`` package (part of the ``setuptools``
43+
distribution) provides a ``require`` function that you can use to check if a
44+
given optional dependency of your package is installed or not:
45+
46+
47+
.. code-block:: python
48+
49+
from pkg_resources import require, DistributionNotFound, VersionConflict
50+
51+
try:
52+
require(["your-package-name[your-extra]"])
53+
except DistributionNotFound:
54+
... # handle package(s) not being installed at all
55+
except VersionConflict:
56+
... # handle version mismatches
57+
58+
Unfortunately, no replacement for this functionality exists in the
59+
``pkg_resources``'s successor packages yet
60+
(`packaging-problems #664 <packaging-problems #664>`_).
61+
62+
63+
------------------
64+
65+
.. _packaging-problems-664: https://github.com/pypa/packaging-problems/issues/664
66+

0 commit comments

Comments
 (0)