Python check if module exists

[python] How to check if a python module exists without importing it

I need to know if a python module exists, without importing it.

Importing something that might not exist (not what I want):

try: import eggs except ImportError: pass 

This question is related to python python-import

The answer is

Python2

To check if import can find something in python2, using imp

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 python3 part

import pkgutil eggs_loader = pkgutil.find_loader('eggs') found = eggs_loader is not None 

Python3

Python3 = 3.3

You should use importlib , How I went about doing this was:

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) 

Python3 = 3.4

In Python3.4 importlib.find_loader python docs 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.

WARNING

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.find_spec("food.eggs") module food loaded ModuleSpec(name='food.eggs', loader=, origin='/home/user/food/eggs.py') 

comments welcome on getting around this

Acknowledgements

  • @rvighne for importlib
  • @lucas-guido for python3.3+ depricating find_loader
  • @enpenax for pkgutils.find_loader behaviour in python2.7

Python 3 >= 3.6: ModuleNotFoundError

The ModuleNotFoundError has been introduced in python 3.6 and can be used for this purpose

try: import eggs except ModuleNotFoundError: # Error handling pass 

The error is raised when a module or one of its parents cannot be found. So

try: import eggs.sub except ModuleNotFoundError as err: # Error handling print(err) 

would print a message that looks like No module named ‘eggs’ if the eggs module cannot be found; but would print something like No module named ‘eggs.sub’ if only the sub module couldn’t be found but the eggs package could be found.

See the documentation of the import system for more info on the ModuleNotFoundError

After use yarbelk’s response, I’ve made this for don’t have to import ìmp .

try: __import__('imp').find_module('eggs') # Make things with supposed existing module except ImportError: pass 

Useful in Django’s settings.py for example.

Python 2, without relying ImportError

Until the current answer is updated, here is the way for Python 2

import pkgutil import importlib if pkgutil.find_loader(mod) is not None: return importlib.import_module(mod) return None 

Why another answer?

A lot of answers make use of catching an ImportError . The problem with that is, that we cannot know what throws the ImportError .

If you import your existant module and there happens to be an ImportError in your module (e.g. typo on line 1), the result will be that your module does not exist. It will take you quite the amount of backtracking to figure out that your module exists and the ImportError is caught and makes things fail silently.

go_as’s answer as a one liner

 python -c "help('modules');" | grep module 

I came across this question while searching for a way to check if a module is loaded from the command line and would like to share my thoughts for the ones coming after me and looking for the same:

Linux/UNIX script file method: make a file module_help.py :

#!/usr/bin/env python help('modules') 

Then make sure it’s executable: chmod u+x module_help.py

And call it with a pipe to grep :

./module_help.py | grep module_name 

Invoke the built-in help system. (This function is intended for interactive use.) If no argument is given, the interactive help system starts on the interpreter console. If the argument is a string, then the string is looked up as the name of a module, function, class, method, keyword, or documentation topic, and a help page is printed on the console. If the argument is any other kind of object, a help page on the object is generated.

Interactive method: in the console load python

If found quit reading by typing q
To exit the python interactive session press Ctrl + D

Windows script file method also Linux/UNIX compatible, and better overall:

#!/usr/bin/env python import sys help(sys.argv[1]) 

Calling it from the command like:

python module_help.py site 

Help on module site:

NAME site — Append module search paths for third-party packages to sys.path.

FILE /usr/lib/python2.7/site.py

MODULE DOCS http://docs.python.org/library/site

DESCRIPTION
.
:

and you’d have to press q to exit interactive mode.

python module_help.py lkajshdflkahsodf 

no Python documentation found for ‘lkajshdflkahsodf’

Use one of the functions from pkgutil, for example:

from pkgutil import iter_modules def module_exists(module_name): return module_name in (name for loader, name, ispkg in iter_modules()) 

I wrote this helper function:

def is_module_available(module_name): if sys.version_info < (3, 0): # python 2 import importlib torch_loader = importlib.find_loader(module_name) elif sys.version_info = (3, 4): # python 3.4 and above import importlib torch_loader = importlib.util.find_spec(module_name) return torch_loader is not None 
import sys print('eggs' in sys.modules) 

You could just write a little script that would try to import all the modules and tell you which ones are failing and which ones are working:

import pip if __name__ == '__main__': for package in pip.get_installed_distributions(): pack_string = str(package).split(" ")[0] try: if __import__(pack_string.lower()): print(pack_string + " loaded successfully") except Exception as e: print(pack_string + " failed with error code: <>".format(e)) 
zope.interface loaded successfully zope.deprecation loaded successfully yarg loaded successfully xlrd loaded successfully WMI loaded successfully Werkzeug loaded successfully WebOb loaded successfully virtualenv loaded successfully . 

Word of warning this will try to import everything so you'll see things like PyYAML failed with error code: No module named pyyaml because the actual import name is just yaml. So as long as you know your imports this should do the trick for you.

You can also use importlib directly

import importlib try: importlib.import_module(module_name) except ImportError: # Handle error 

There is no way to reliably check if "dotted module" is importable without importing its parent package. Saying this, there are many solutions to problem "how to check if Python module exists".

Below solution address the problem that imported module can raise ImportError even it exists. We want to distinguish that situation from such in which module does not exist.

import importlib import pkgutil import sys def find_module(full_module_name): """ Returns module object if module `full_module_name` can be imported. Returns None if module does not exist. Exception is raised if (existing) module raises exception during its import. """ module = sys.modules.get(full_module_name) if module is None: module_path_tail = full_module_name.split('.') module_path_head = [] loader = True while module_path_tail and loader: module_path_head.append(module_path_tail.pop(0)) module_name = ".".join(module_path_head) loader = bool(pkgutil.find_loader(module_name)) if not loader: # Double check if module realy does not exist # (case: full_module_name == 'paste.deploy') try: importlib.import_module(module_name) except ImportError: pass else: loader = True if loader: module = importlib.import_module(full_module_name) return module 
import importlib def find_module(full_module_name): """ Returns module object if module `full_module_name` can be imported. Returns None if module does not exist. Exception is raised if (existing) module raises exception during its import. """ try: return importlib.import_module(full_module_name) except ImportError as exc: if not (full_module_name + '.').startswith(exc.name + '.'): raise 
 import sys import os import imp def module_has_submodule(package, module_name): """ check module in package django.utils.module_loading.module_has_submodule """ name = ".".join([package.__name__, module_name]) try: # None indicates a cached miss; see mark_miss() in Python/import.c. return sys.modules[name] is not None except KeyError: pass try: package_path = package.__path__ # No __path__, then not a package. except AttributeError: # Since the remainder of this function assumes that we're dealing with # a package (module with a __path__), so if it's not, then bail here. return False for finder in sys.meta_path: if finder.find_module(name, package_path): return True for entry in package_path: try: # Try the cached finder. finder = sys.path_importer_cache[entry] if finder is None: # Implicit import machinery should be used. try: file_, _, _ = imp.find_module(module_name, [entry]) if file_: file_.close() return True except ImportError: continue # Else see if the finder knows of a loader. elif finder.find_module(name): return True else: continue except KeyError: # No cached finder, so try and make one. for hook in sys.path_hooks: try: finder = hook(entry) # XXX Could cache in sys.path_importer_cache if finder.find_module(name): return True else: # Once a finder is found, stop the search. break except ImportError: # Continue the search for a finder. continue else: # No finder found. # Try the implicit import machinery if searching a directory. if os.path.isdir(entry): try: file_, _, _ = imp.find_module(module_name, [entry]) if file_: file_.close() return True except ImportError: pass # XXX Could insert None or NullImporter else: # Exhausted the search, so the module cannot be found. return False 

Источник

Читайте также:  Php вывод массива построчно
Оцените статью