How to Resolve Python "AttributeError: type object 'EntryPoints' has no attribute 'get'"
When working with Python packaging tools or libraries that interact with package metadata, you might encounter the AttributeError: type object 'EntryPoints' has no attribute 'get'
. This error typically arises after updating tools or environments and indicates an incompatibility with newer versions of the importlib-metadata
package (specifically version 5.0 and above).
This guide explains the change in importlib-metadata
that causes this error and provides clear solutions to resolve it, primarily by managing the package version.
Understanding the Error: Entry Points and importlib-metadata
- Entry Points: A feature used by Python packages to advertise certain components (like plugins or command-line scripts) in a discoverable way. Other tools or applications can then find and load these components using the package metadata.
importlib-metadata
: A library (built-in to Python 3.8+ but also available as a backport/standalone package) that provides access to the metadata of installed Python packages, including their entry points.- The
.get()
Method: Older ways of accessing entry points, often via interfaces similar to the deprecatedpkg_resources
library, involved using a.get()
method on anEntryPoints
object (sometimes accessed directly as a class attribute in certain contexts).
The error AttributeError: type object 'EntryPoints' has no attribute 'get'
means your code (or a library your code is using) is trying to use this older .get()
method pattern, which is no longer available on the relevant object provided by newer versions of importlib-metadata
.
The Cause: API Changes in importlib-metadata
v5.0+
Starting with version 5.0, the importlib-metadata
library removed compatibility shims that supported the older pkg_resources
-style entry point access patterns, including the .get()
method used in this way. The modern API uses functions like importlib.metadata.entry_points()
which returns a different type of object (a SelectableGroups
object, which yields EntryPoint
objects upon selection/iteration) that uses methods like .select()
instead of .get()
for lookup.
Therefore, the error occurs when code written for the older interface runs in an environment with importlib-metadata
version 5.0 or higher installed.
Conceptual Example of Old vs New (Illustrative):
import importlib.metadata # Assume appropriate version
# --- OLDER pattern that might cause error with importlib-metadata >= 5.0 ---
try:
# This specific pattern might vary, but the idea is using .get()
# on something representing the collection of entry points.
eps = importlib.metadata.entry_points # Hypothetical older access
my_plugin = eps.get('my_plugin_group', 'plugin_name') # This .get() is the issue
print("Found plugin (old way)")
except AttributeError as e:
print(f"Error (likely): {e}") # "'EntryPoints' object has no attribute 'get'"
import importlib.metadata # Assume appropriate version
# --- MODERN pattern (importlib-metadata >= 3.6 approx) ---
try:
all_eps = importlib.metadata.entry_points()
# New API uses .select() or iteration
selected_eps = all_eps.select(group='my_plugin_group', name='plugin_name')
my_plugin_entry = next(iter(selected_eps), None) # Get the first match or None
if my_plugin_entry:
print(f"Found plugin (new way): {my_plugin_entry.name}")
else:
print("Plugin not found (new way)")
except Exception as e:
print(f"Error (new way): {e}")
Solution 1: Pin importlib-metadata
Version to < 5.0
(Common Fix)
The most common and often easiest immediate fix is to prevent the installation of importlib-metadata
version 5.0 or higher. You force pip to install the latest version before 5.0 (which is typically 4.13.0
). This retains the older API that the problematic code expects.
Installing an Older Version via Pip
Run the following command in your terminal (activate your virtual environment first if applicable):
# Install latest version LESS THAN 5.0
pip install "importlib-metadata<5.0"
# --- OR using specific pip variants ---
pip3 install "importlib-metadata<5.0"
python -m pip install "importlib-metadata<5.0"
python3 -m pip install "importlib-metadata<5.0"
py -m pip install "importlib-metadata<5.0" # Windows py launcher
# --- OR for Jupyter/Colab ---
!pip install "importlib-metadata<5.0"
This command tells pip to find the highest version number strictly less than 5.0.
Pinning in requirements.txt
To make this fix permanent for your project, add the version constraint to your requirements.txt
file:
# requirements.txt
# ... other dependencies ...
importlib-metadata<5.0
# ... other dependencies ...
Then run pip install -r requirements.txt
.
Specific Version (==4.13.0
)
You can also pin to the exact last version before 5.0:
pip install importlib-metadata==4.13.0
And in requirements.txt
:
importlib-metadata==4.13.0
Pinning with <5.0
is slightly more flexible as it allows potential future patch releases within the 4.x series, while ==4.13.0
locks it precisely. Choose based on your project's needs.
Solution 2: Update Calling Code/Dependencies (Long-Term Fix)
The "correct" long-term solution is to update the code that is calling the entry point methods to use the modern importlib.metadata
API (e.g., using entry_points().select(...)
or iterating over entry_points()
).
- If the error is in your own code: Refactor your code to use the new API as shown conceptually in Section 2. Consult the
importlib.metadata
documentation for the exact usage. - If the error is in a third-party library:
- Check for updates to that library (
pip install --upgrade library-name
). Newer versions might already include fixes for compatibility withimportlib-metadata >= 5.0
. - If no update is available, check the library's issue tracker. Report the incompatibility if it hasn't been already.
- In this case, pinning
importlib-metadata<5.0
(Solution 1) becomes the necessary workaround until the third-party library is updated.
- Check for updates to that library (
Solution 3: Check Python Version Compatibility
While the importlib-metadata
v5.0 change is the direct trigger, ensure you are using a reasonably modern Python version (generally Python 3.8+ is recommended, as importlib.metadata
became standard then). Very old Python versions might bundle incompatible older versions of importlib-metadata
or prevent pip
from installing a version that works correctly, even when pinned.
Check your version:
python --version
# Or:
python3 --version
If you are on a very old version (like Python 3.6 or older), consider upgrading your Python environment.
Debugging: Verifying the Installed Version (pip show
)
After attempting to pin the version, verify that the correct version is actually installed in your environment:
pip show importlib-metadata
# Or use pip3 / python -m pip show if needed
Check the Version:
line in the output. It should show a version like 4.13.0
or another 4.x
version if you used <5.0
. If it still shows 5.0.0
or higher, the pinning/installation command might not have executed correctly in the target environment.
Specific Case: Redash Compatibility
Some users (particularly with older versions of tools like Redash) reported needing to pin to an even earlier version, specifically 4.12.0
. If pinning to <5.0
or 4.13.0
doesn't work in such specific contexts, try:
pip install importlib-metadata==4.12.0
And in requirements.txt
:
importlib-metadata==4.12.0
Conclusion
The AttributeError: type object 'EntryPoints' has no attribute 'get'
is primarily caused by the API changes introduced in importlib-metadata
version 5.0 and newer, which removed backward-compatibility for older entry point access patterns.
The most common and effective solutions are:
- Pin
importlib-metadata
: Force installation of a version less than 5.0 usingpip install "importlib-metadata<5.0"
or by addingimportlib-metadata<5.0
(or==4.13.0
) to yourrequirements.txt
. - Update Code/Dependencies: If possible, modify the code calling the entry point methods to use the modern
importlib.metadata
API, or update the third-party library causing the error. - Check Python Version: Ensure you are using a reasonably modern Python version (3.8+ recommended).
Pinning the version is often the quickest workaround, especially when the problematic code is in a dependency you cannot easily modify.