I've seen several approaches for finding the path of a module by first importing it. Is there a way to do this without importing the module?
-
1Why? Why don't you want to import it?user225312– user2253122011-01-14 16:53:33 +00:00Commented Jan 14, 2011 at 16:53
-
10Because importing is useless at the point in the program where the paths are needed and can cause circular dependencies and other issues. Import occurs at a more opportune time later down the road.jeffcook2150– jeffcook21502011-01-14 17:00:25 +00:00Commented Jan 14, 2011 at 17:00
-
1Also you may want to just look at the source code without actually running any code in the module.BrockLee– BrockLee2017-02-27 20:45:44 +00:00Commented Feb 27, 2017 at 20:45
5 Answers
Using pkgutil module:
>>> import pkgutil
>>> package = pkgutil.get_loader("pip")
>>> package.filename
'/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip'
>>> package = pkgutil.get_loader("threading")
>>> package.filename
'/usr/lib/python2.6/threading.py'
>>> package = pkgutil.get_loader("sqlalchemy.orm")
>>> package.filename
'/usr/lib/pymodules/python2.6/sqlalchemy/orm'
In Python 3, use pkgutil.get_loader("module name").get_filename() instead.
Using imp module:
>>> import imp
>>> imp.find_module('sqlalchemy')
(None, '/usr/lib/pymodules/python2.6/sqlalchemy', ('', '', 5))
>>> imp.find_module('pip')
(None, '/usr/local/lib/python2.6/dist-packages/pip-0.7.1-py2.6.egg/pip', ('', '', 5))
>>> imp.find_module('threading')
(<open file '/usr/lib/python2.6/threading.py', mode 'U' at 0x7fb708573db0>, '/usr/lib/python2.6/threading.py', ('.py', 'U', 1))
N.B: with imp module you can't do something like imp.find_module('sqlalchmy.orm')
6 Comments
pkgutil doesn't do what is requested in all cases. pkgutil.get_laoder("sqlalchemy.orm") wll execute sqlalchemy/__init__.py, tho it won't execute sqlalchemy/orm.py.__init__.py package as the documentation (docs.python.org/release/3.1.5/library/…) say If the named module is not already imported, its containing package (if any) is imported, in order to establish the package _path_ which make total sense :)pkgutil.get_loader is deprecated, one should use importlib.util.find_spec insteadFor python3 imp is deprecated. Use pkgutil (as seen above) or for Python 3.4+ use importlib.util.find_spec:
>>> import importlib
>>> spec = importlib.util.find_spec("threading")
>>> spec.origin
'/usr/lib64/python3.6/threading.py'
5 Comments
__init__.py. Use instead : python >>> spec.submodule_search_locations[0] find_spec might try importing the module github.com/python/cpython/blob/…find_spec is not used to find submodules: find_spec("foo") will not import anything but find_spec("foo.bar") will import foo (thereby evaluating foo.__init__.py)For most use-cases, you actually don't need help from third parties. importlib.util.find_spec has been around since python3.4, and solves the issue for top-level imports:
>>> import importlib.util
>>> spec = importlib.util.find_spec("foo")
>>> spec.origin
/home/me/my_venv/python3.11/site-packages/foo/__init__.py
And for a portable variant that gets the parent folder:
[...]
>>> from pathlib import Path
>>> Path(spec.origin).parent
/home/me/my_venv/python3.11/site-packages/foo
Notes:
- For sub-packages (e.g.
foo.bar), parent packages will be actually imported. Due to the dynamic nature of python, including how imports may resolve, there is no correct solution which does not do an actual import (try to find the location ofos.pathwithout importingosfor a real-world-example). - If the package doesn't exist,
specwill beNone. - If the package is actually a namespace,
spec.originwill beNone
Comments
import importlib.util
import os
this_module='numpy'
origin=importlib.util.find_spec(this_module).origin
print(origin)
path_to_this_module=os.path.dirname(origin)
print(path_to_this_module)
Output on windows:
...\site-packages\numpy\__init__.py
...\site-packages\numpy
Output on linux:
/home/.../site-packages/numpy/__init__.py
/home/.../site-packages/numpy
Comments
You might want to try running this in your interpreter:
>>> import sys
>>> sys.modules['codecs'].__file__ # codecs is just an example
'/usr/lib/python2.7/codecs.pyc'