Python
programming
module
troubleshooting
source code

How do I find the location of Python module sources?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To find where a Python module's source code is located on disk, use module.__file__, inspect.getfile(module), or run python -m site to see all module search paths. This is useful for debugging import issues, reading library source code, finding which version of a module is actually imported, and locating configuration files installed alongside packages.

Method 1: module.file

The __file__ attribute contains the path to the module's source file:

python
1import os
2print(os.__file__)
3# /usr/lib/python3.11/os.py
4
5import json
6print(json.__file__)
7# /usr/lib/python3.11/json/__init__.py
8
9import requests
10print(requests.__file__)
11# /home/user/.local/lib/python3.11/site-packages/requests/__init__.py

For packages (directories with __init__.py), __file__ points to __init__.py. The parent directory is the package root.

Handling Missing file

Some built-in modules (written in C) do not have __file__:

python
1import sys
2print(hasattr(sys, '__file__'))  # False — sys is a built-in C module
3
4import math
5print(hasattr(math, '__file__'))  # May be False on some platforms

Check first:

python
1def get_module_path(module):
2    if hasattr(module, '__file__') and module.__file__:
3        return module.__file__
4    return f"{module.__name__} is a built-in module (no file)"
5
6import os, sys
7print(get_module_path(os))   # /usr/lib/python3.11/os.py
8print(get_module_path(sys))  # sys is a built-in module (no file)

Method 2: inspect.getfile()

The inspect module provides a more robust way:

python
1import inspect
2import os
3import json
4import collections
5
6print(inspect.getfile(os))           # /usr/lib/python3.11/os.py
7print(inspect.getfile(json))         # /usr/lib/python3.11/json/__init__.py
8print(inspect.getfile(collections))  # /usr/lib/python3.11/collections/__init__.py
9
10# Works on classes and functions too
11from pathlib import Path
12print(inspect.getfile(Path))  # /usr/lib/python3.11/pathlib.py

inspect.getfile() raises TypeError for built-in modules:

python
1import sys
2try:
3    print(inspect.getfile(sys))
4except TypeError as e:
5    print(e)  # <module 'sys' (built-in)> is a built-in module

Method 3: From the Command Line

pip show

bash
1# Shows package location and metadata
2pip show requests
3
4# Output:
5# Name: requests
6# Version: 2.31.0
7# Location: /home/user/.local/lib/python3.11/site-packages

python -c

bash
1# One-liner to print module path
2python -c "import requests; print(requests.__file__)"
3# /home/user/.local/lib/python3.11/site-packages/requests/__init__.py
4
5python -c "import numpy; print(numpy.__file__)"
6# /home/user/.local/lib/python3.11/site-packages/numpy/__init__.py

python -m site

bash
1# Show all module search paths
2python -m site
3
4# Output includes:
5# sys.path = [
6#     '/home/user/project',
7#     '/usr/lib/python3.11',
8#     '/usr/lib/python3.11/lib-dynload',
9#     '/home/user/.local/lib/python3.11/site-packages',
10#     '/usr/lib/python3.11/site-packages',
11# ]

Method 4: sys.path and Import Search Order

Python searches for modules in directories listed in sys.path:

python
1import sys
2
3for path in sys.path:
4    print(path)
5
6# Output (typical):
7# /home/user/project          (current directory)
8# /usr/lib/python3.11         (standard library)
9# /usr/lib/python3.11/lib-dynload
10# /home/user/.local/lib/python3.11/site-packages  (user packages)
11# /usr/lib/python3.11/site-packages               (system packages)

Python checks these paths in order. The first match wins:

python
# Which 'json' module is actually imported?
import json
print(json.__file__)  # Verifies it's the standard library, not a local file named json.py

Method 5: importlib

python
1import importlib.util
2
3spec = importlib.util.find_spec('requests')
4if spec:
5    print(spec.origin)       # /.../.../requests/__init__.py
6    print(spec.submodule_search_locations)  # Package directories
7
8# Check if a module exists without importing it
9spec = importlib.util.find_spec('nonexistent')
10print(spec)  # None

Finding the Source Directory

python
1import os
2import requests
3
4# Get the directory containing the module
5module_dir = os.path.dirname(requests.__file__)
6print(module_dir)
7# /home/user/.local/lib/python3.11/site-packages/requests
8
9# List files in the module directory
10for f in sorted(os.listdir(module_dir)):
11    print(f)
12# __init__.py
13# adapters.py
14# api.py
15# auth.py
16# ...

Virtual Environment Module Locations

bash
1# Activate a virtual environment
2source venv/bin/activate
3
4# Modules install into the venv's site-packages
5python -c "import requests; print(requests.__file__)"
6# /home/user/project/venv/lib/python3.11/site-packages/requests/__init__.py
7
8# Show all paths
9python -c "import site; print(site.getsitepackages())"
10# ['/home/user/project/venv/lib/python3.11/site-packages']

Common Pitfalls

  • Shadowing standard library modules with local files: A file named json.py or random.py in your project directory shadows the standard library module. Python searches the current directory first, so your local file gets imported instead.
  • Built-in modules have no __file__: Modules like sys, builtins, and sometimes math are implemented in C and compiled into the interpreter. They have no file path. Check hasattr(module, '__file__') before accessing it.
  • Confusing .pyc with .py paths: __file__ may point to a .pyc (compiled bytecode) file instead of the .py source. Use importlib.util.find_spec() which reports the source file, or check if a .py file exists at the same path.
  • Different module paths in virtual environments: A module may be installed globally and in a virtual environment. The path depends on which Python interpreter is active. Always verify with python -c "import x; print(x.__file__)" from the intended environment.
  • Editable installs (pip install -e) point to the source directory: Editable installs symlink to the development directory. The module path reflects the source location, not site-packages, which can be confusing when debugging import issues.

Summary

  • Use module.__file__ for the quickest way to find a module's source file
  • Use inspect.getfile(module) for a more robust alternative that also works on classes and functions
  • Use pip show package_name from the command line to find package location and metadata
  • Use importlib.util.find_spec() to find a module path without importing it
  • Check sys.path to understand the import search order and debug shadowing issues

Course illustration
Course illustration

All Rights Reserved.