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:
- First, to resolve the top-level package name into a module with a
__path__attribute - 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_packagesrecursively finds all Python files underholehe.modulesimportlib.import_moduleconverts discovered names into loaded module objects- Together they provide a zero-configuration, drop-in architecture for new services
- The
import_submodulesandget_functionsutilities inholehe/core.pyorchestrate 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →