Asked By – yarbelk
How can I know if a Python module exists, without importing it?
Importing something that might not exist (not what I want) results in:
try: import eggs except ImportError: pass
Now we will see solution for issue: How to check if a Python module exists without importing it
To check if import can find something in Python 2, using
import imp try: imp.find_module('eggs') found = True except ImportError: found = False
To find dotted imports, you need to do more:
import imp try: spam_info = imp.find_module('spam') spam = imp.load_module('spam', *spam_info) imp.find_module('eggs', spam.__path__) # __path__ is already a list found = True except ImportError: found = False
You can also use
pkgutil.find_loader (more or less the same as the Python 3 part:
import pkgutil eggs_loader = pkgutil.find_loader('eggs') found = eggs_loader is not None
Python 3 ≤ 3.3
You should use
importlib. I went about doing this like:
import importlib spam_loader = importlib.find_loader('spam') found = spam_loader is not None
My expectation being, if you can find a loader for it, then it exists. You can also be a bit more smart about it, like filtering out what loaders you will accept. For example:
import importlib spam_loader = importlib.find_loader('spam') # only accept it as valid if there is a source file for the module - no bytecode only. found = issubclass(type(spam_loader), importlib.machinery.SourceFileLoader)
Python 3 ≥ 3.4
In Python 3.4
importlib.find_loader Python documentation was deprecated in favour of
importlib.util.find_spec. The recommended method is the
importlib.util.find_spec. There are others like
importlib.machinery.FileFinder, which is useful if you’re after a specific file to load. Figuring out how to use them is beyond the scope of this.
import importlib spam_spec = importlib.util.find_spec("spam") found = spam_spec is not None
This also works with relative imports, but you must supply the starting package, so you could also do:
import importlib spam_spec = importlib.util.find_spec("..spam", package="eggs.bar") found = spam_spec is not None spam_spec.name == "eggs.spam"
While I’m sure there exists a reason for doing this – I’m not sure what it would be.
When trying to find a submodule, it will import the parent module (for all of the above methods)!
food/ |- __init__.py |- eggs.py ## __init__.py print("module food loaded") ## eggs.py print("module eggs") were you then to run >>> import importlib >>> spam_spec = importlib.util.find_spec("food.eggs") module food loaded ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')
Comments are welcome on getting around this
- @rvighne for importlib
- @lucas-guido for Python 3.3+ deprecating
- @enpenax for pkgutils.find_loader behaviour in Python 2.7