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?
Asked
Active
Viewed 1.5k times
54
-
1Why? Why don't you want to import it? – user225312 Jan 14 '11 at 16:53
-
9Because 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 Jan 14 '11 at 17:00
-
1Also you may want to just look at the source code without actually running any code in the module. – BrockLee Feb 27 '17 at 20:45
4 Answers
70
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')

Jules G.M.
- 3,624
- 1
- 21
- 35

mouad
- 67,571
- 18
- 114
- 106
-
@cgohlke : actually their is no __pkutil__ package, it should be __pkgutil__, it was a typo mistake , thanks for pointing it out :) – mouad Jan 14 '11 at 18:46
-
1@mouad I'm actually looking for the same thing. The above implementation with `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`. – Prody Jul 14 '12 at 18:46
-
2@Prody: Yes that's true in case of a package it will execute the ``__init__.py`` package as the documentation (http://docs.python.org/release/3.1.5/library/pkgutil.html#pkgutil.get_loader) 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 :) – mouad Jul 14 '12 at 22:33
-
12I found [in Python 3.5.1] that package.filename didn't exist, but package.get_filename() did. – Oddthinking Oct 25 '16 at 02:30
-
It sometimes doesn't work for Python3.11 . For example, how can I get the location of `os.py` (os stdlib) in Python3.11? – tamuhey Feb 10 '23 at 11:11
15
For 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'

Bryce Guinta
- 3,456
- 1
- 35
- 36
-
spec.origin attribute do not exist for a module folder which contains an `__init__.py`. Use instead : ```python >>> spec.submodule_search_locations[0] ``` – Cyril Waechter Jan 15 '21 at 10:39
-
2unfortunately `find_spec` might try importing the module https://github.com/python/cpython/blob/ec2385e315fc6b28d92dfb4c97fefcbb1e7daa68/Lib/importlib/util.py#L94 – karlicoss Feb 19 '21 at 01:04
-
This will only work if `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`) – JustinBull Jun 06 '22 at 16:39
-
-
@tamuhey that means the module was compiled into byte code and included in an a standalone python interpreter. i.e. it has no location – Bryce Guinta May 08 '23 at 15:23
0
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'

Noctis Skytower
- 21,433
- 16
- 79
- 117

virhilo
- 6,568
- 2
- 29
- 26
-
+1 I would have suggested a DFS or something using os.system. But this is awesome - didn't know this could be done – inspectorG4dget Jan 14 '11 at 16:58
-
This doesn't work except with some modules from the stdlib. Try it with SQLAlchemy. Thanks for the response, though. – jeffcook2150 Jan 14 '11 at 16:59
-
15
-
0
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.path
without importingos
for a real-world-example). - If the package doesn't exist,
spec
will beNone
. - If the package is actually a namespace,
spec.origin
will beNone

Arne
- 17,706
- 5
- 83
- 99