Skip to content

Instantly share code, notes, and snippets.

@kdart
Last active September 4, 2018 02:58
Show Gist options
  • Save kdart/652ddd73fa0afe226457 to your computer and use it in GitHub Desktop.
Save kdart/652ddd73fa0afe226457 to your computer and use it in GitHub Desktop.
Python 3 script that can tell you where a module is coming from when imported.
#!/usr/bin/env python3.7
"""
Uses the import machinery to locate a module and report what it found, such as
where the source file is.
"""
import sys
import os
import importlib
import importlib.util
import getopt
def module_from_path(fname):
"""Find and return the module name given a full path name.
Return None if file name not in the package path.
"""
if not os.path.exists(fname):
print("Warning: given path name does not exist.", file=sys.stderr)
dirname, basename = os.path.split(fname)
for p in sys.path:
if fname.startswith(p):
pkgname = ".".join(dirname[len(p)+1:].split("/"))
if pkgname:
return pkgname + "." + os.path.splitext(basename)[0]
else:
return os.path.splitext(basename)[0]
return None
def getmod(args):
for fname in args:
modname = module_from_path(fname)
if modname:
print(modname)
def pyfiles(args):
for modname in args:
spec = importlib.util.find_spec(modname)
if spec:
if spec.has_location:
if spec.loader.is_package(modname):
mod = importlib.import_module(spec.name)
for p in mod.__path__:
print(p)
else:
print(spec.origin)
else:
print(spec.cached)
else:
print("{} not found.".format(modname))
def pywhich(args):
for modname in args:
try:
spec = importlib.util.find_spec(modname)
except ValueError:
mod = sys.modules[modname]
for p in mod.__path__:
print(" {}".format(p))
return
if spec:
if spec.has_location:
if spec.loader.is_package(modname):
print("{} is a package -> {}\nPaths:".format(spec.name, spec.origin))
mod = importlib.import_module(spec.name)
for p in mod.__path__:
print(" {}".format(p))
else:
cached = "(cached)" if spec.cached else ""
print("{} -> {} {}".format(spec.name, spec.origin, cached))
else:
print("No source location.")
else:
print("Not found.")
def main(argv):
"""pywhich [-fr] <modname>
Tell you which actual file is being used by an import. The module name
should be a full module path (e.g. pycopia.OS.rtc).
If the `-f` option is given then give the full path name to the source
file, if available. If it's a package then the package search paths are printed.
Use -r for a reverse mapping. Given a file, find the module name used to
import it.
"""
do_file = False
do_reverse = False
try:
opts, args = getopt.getopt(sys.argv[1:], "h?fr", ["help", "file",
"reverse"])
except getopt.GetoptError as err:
print(str(err))
print(main.__doc__)
return 1
for option, argument in opts:
if option in ("-h", "--help"):
print(main.__doc__)
return 2
elif option in ("-f", "--file"):
do_file = True
elif option in ("-r", "--reverse"):
do_reverse = True
if not args:
print(main.__doc__)
return 1
if do_reverse:
return getmod(args)
elif do_file:
return pyfiles(args)
else:
return pywhich(args)
sys.exit(main(sys.argv))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment