jeffcook2150
jeffcook2150

Reputation: 4226

Find path of module without importing in Python

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?

Upvotes: 66

Views: 18327

Answers (5)

learner
learner

Reputation: 656

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

Upvotes: 0

Arne
Arne

Reputation: 20245

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 of os.path without importing os for a real-world-example).
  • If the package doesn't exist, spec will be None.
  • If the package is actually a namespace, spec.origin will be None

Upvotes: 1

mouad
mouad

Reputation: 70089

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')

Upvotes: 72

Bryce Guinta
Bryce Guinta

Reputation: 3752

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'

Upvotes: 20

virhilo
virhilo

Reputation: 6793

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'

Upvotes: -1

Related Questions