What Python Modules Are Used for Holehe's Module Discovery?

Holehe uses importlib and pkgutil from the Python standard library to dynamically discover and load its service-checking modules at runtime.

The open-source email intelligence tool Holehe automatically finds every module under holehe.modules without hardcoding paths. This plug-and-play architecture lets contributors add new services by simply dropping Python files into the package hierarchy. Understanding what Python modules are used for Holehe's module discovery reveals how the tool maintains its extensible, zero-configuration design.

The Two Standard Library Modules Behind Discovery

Holehe's discovery mechanism relies entirely on two stable, well-documented packages: pkgutil for enumeration and importlib for loading.

pkgutil.walk_packages: Finding Every Submodule

The pkgutil module provides walk_packages, which recursively traverses a package's filesystem tree. In holehe/core.py, this function yields each submodule's loader, name, and whether it's a package—effectively discovering every .py file under holehe.modules without prior knowledge of the directory structure.


# Simplified excerpt from holehe/core.py showing pkgutil usage

import pkgutil
import importlib

def import_submodules(package, recursive=True):
    """Import all submodules of a package, recursively."""
    package = importlib.import_module(package)
    results = {}
    for loader, name, is_pkg in pkgutil.walk_packages(package.__path__):
        full_name = package.__name__ + '.' + name
        results[full_name] = importlib.import_module(full_name)
    return results

pkgutil.walk_packages is the core enumerator that makes Holehe's architecture possible.

importlib.import_module: Turning Paths Into Live Modules

The importlib module provides import_module, which converts a dotted module name (e.g., holehe.modules.social_media.twitter) into a live Python module object. This is called twice in the discovery flow:

  1. First, to resolve the top-level package name into a module with a __path__ attribute
  2. Then, for each discovered submodule, to actually load it into memory

According to the Holehe source code, importlib.import_module bridges the gap between filesystem paths and executable Python code.

How the Discovery Flow Works

The complete process in holehe/core.py transforms the static holehe/modules/ directory into a list of callable functions:

Step 1: Enumerate and import

from holehe.core import import_submodules

all_modules = import_submodules("holehe.modules")

# Returns: {'holehe.modules.social_media.twitter': <module>,

#           'holehe.modules.social_media.instagram': <module>,

#           ...}

Step 2: Extract service functions

The get_functions(modules, args) helper then inspects each imported module for callable check functions, filtering and preparing them for execution.

from holehe.core import get_functions

service_functions = get_functions(all_modules)

# Returns a list of callable functions like twitter(email), instagram(email), etc.

Practical Example: Listing Available Services

Here's a complete script demonstrating what Python modules are used for Holehe's module discovery in practice:

from holehe.core import import_submodules, get_functions

# Discover all modules under holehe.modules

all_modules = import_submodules("holehe.modules")

# Convert to callable check functions

service_functions = get_functions(all_modules)

# Display discovered services

print(f"Found {len(service_functions)} services:\n")
for fn in service_functions:
    doc = fn.__doc__ or "No description available"
    print(f"  {fn.__name__:20} → {doc.split(chr(10))[0]}")

Output resembles:


Found 120+ services:

  twitter              → Check if a Twitter account uses the email
  instagram            → Verify Instagram account association
  github               → Query GitHub for the email address
  ...

Key Source Files

File Purpose
holehe/core.py Contains import_submodules() and get_functions()
holehe/modules/__init__.py Package marker enabling discovery
holehe/modules/social_media/twitter.py Example service implementation

These files demonstrate how importlib and pkgutil enable Holehe's automatic discovery without explicit registration or configuration files.

Summary

  • pkgutil.walk_packages recursively finds all Python files under holehe.modules
  • importlib.import_module converts discovered names into loaded module objects
  • Together they provide a zero-configuration, drop-in architecture for new services
  • The import_submodules and get_functions utilities in holehe/core.py orchestrate the flow
  • No third-party dependencies are required for the discovery mechanism itself

Frequently Asked Questions

Does Holehe require any third-party packages for module discovery?

No. The entire discovery mechanism relies strictly on Python's standard library. Both importlib and pkgutil have been part of Python since version 2.7/3.1, making Holehe's discovery logic highly portable and maintenance-free.

What happens if a module fails to import?

The import_submodules function in holehe/core.py catches import errors during the importlib.import_module calls. Failed modules are typically skipped rather than crashing the entire discovery process, ensuring that a broken service implementation doesn't disable the whole tool.

How does Holehe handle nested subpackages like holehe.modules.social_media?

pkgutil.walk_packages with recursive=True (the default in Holehe) automatically descends into subdirectories. The function yields the loader, name, and is_pkg flag for every level, allowing importlib to load modules regardless of nesting depth. This is how services in social_media/, shopping/, entertainment/, and other categories are all discovered uniformly.

Can I use this same pattern for my own plugin system?

Yes. The combination of pkgutil.walk_packages and importlib.import_module is a canonical Python pattern for plugin discovery. The key requirements are: (1) your plugins must be importable Python packages with __path__ attributes, and (2) you need a consistent way to identify and extract your plugin classes or functions from the loaded modules—exactly what Holehe's get_functions helper demonstrates.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →