# How Holehe Dynamically Loads Modules: Runtime Discovery in megadose/holehe

> Discover how Holehe dynamically loads modules. Learn about pkgutil walk_packages, importlib, and async execution with trio for efficient runtime discovery in megadose/holehe.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: internals
- Published: 2026-09-08

---

**Holehe dynamically loads modules by using `pkgutil.walk_packages` to discover Python files under `holehe/modules`, `importlib` to load them, and a custom filtering mechanism to extract the service-checking functions for async execution via `trio`.**

The open-source OSINT tool `megadose/holehe` validates email address usage across hundreds of online services without hardcoded import statements for each platform. By implementing a runtime module discovery system in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), the tool achieves a **plug-and-play architecture** where adding new services requires only dropping a Python file into the correct directory structure.

## The Three-Stage Dynamic Loading Pipeline

The dynamic loading mechanism operates through three coordinated phases that transform filesystem modules into executable coroutines.

### Stage 1: Package Discovery via `import_submodules`

The `import_submodules` function (lines 36-46 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) initiates the discovery process by traversing the package tree under `holehe.modules`. Using `pkgutil.walk_packages`, it iterates through every subdirectory and Python file, then calls `importlib.import_module` to load each discovered sub-module into memory. This approach eliminates the need for explicit import statements in the codebase, allowing the tool to recognize new services immediately upon file creation.

### Stage 2: Function Extraction with `get_functions`

Once modules are loaded, the `get_functions` utility (lines 50-63 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) filters the results to extract the actual checking functions. It receives the dictionary from `import_submodules`, iterates over fully-qualified module names (such as `holehe.modules.social_media.twitter`), and selects entries matching the expected directory depth. For qualifying modules, it retrieves the callable object that shares the module's final component name—the specific function that performs the email verification request.

### Stage 3: Async Execution in `maincore`

The `maincore` function (lines 95-122 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) orchestrates execution by invoking the previous two stages and spawning concurrent tasks. It passes the extracted functions to `trio` for asynchronous execution, enabling simultaneous checks against multiple services without blocking. Each callable runs as an independent task, aggregating results into a unified output format.

## File Structure and Implementation Details

The dynamic loader relies on strict conventions within the repository structure. The `holehe/modules/` directory contains subdirectories categorizing services (such as `social_media`, `shopping`, or `productivity`), with each Python file named after the service it checks. The loader expects each file to define a function matching its filename—creating a direct mapping between the filesystem and the executable code.

According to the `megadose/holehe` source code, the implementation uses standard library components rather than third-party dependency injection frameworks. The `pkgutil.walk_packages` call recursively inspects the `holehe.modules` namespace, while `importlib.import_module` handles the actual module instantiation. This design keeps dependencies minimal while maximizing extensibility.

## Working with the Dynamic Loader

Developers can interact with Holehe's module system both programmatically and through the command line interface.

### Manual Module Loading

To inspect or invoke the discovered functions directly:

```python
from holehe.core import import_submodules, get_functions

# Discover and load every module under holehe.modules

mods = import_submodules("holehe.modules")

# Extract the service-checking functions (e.g., twitter, instagram)

functions = get_functions(mods)

# Execute or inspect the loaded functions

for fn in functions:
    print(f"Loaded: {fn.__name__}")

```

### CLI Execution

The command-line interface automates this process:

```bash
holehe victim@example.com

```

Behind the scenes, the CLI executes `maincore`, which performs the dynamic loading pipeline and runs each function concurrently using `trio`.

## Summary

- **`import_submodules`** in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) uses `pkgutil.walk_packages` to discover all Python modules under `holehe/modules` without explicit imports.
- **`get_functions`** filters the discovered modules by depth and extracts the checking functions that match their filenames.
- **`maincore`** combines these utilities to load modules at runtime and execute them asynchronously via `trio`.
- The architecture enables a plug-and-play system where adding services requires only creating new files in `holehe/modules/` subdirectories.

## Frequently Asked Questions

### How does Holehe discover new service modules without explicit imports?

Holehe uses `pkgutil.walk_packages` to recursively scan the `holehe.modules` package tree at runtime. When it encounters a new Python file in any subdirectory of `holehe/modules/`, it automatically loads the module using `importlib.import_module`, making the service available immediately without modifying any import statements in the core code.

### What is the role of `pkgutil.walk_packages` in Holehe's architecture?

The `pkgutil.walk_packages` function serves as the discovery engine in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). It traverses the entire module hierarchy under `holehe.modules`, yielding information about every sub-package and module found. This allows Holehe to maintain a modular structure where services are organized by category (social media, shopping, etc.) while the loader treats them as a flat collection of callable functions.

### How does Holehe execute multiple service checks concurrently?

After extracting the checking functions via `get_functions`, the `maincore` function passes them to `trio` to create an asynchronous task for each service. Each task runs the service-specific check independently, allowing hundreds of email verification requests to execute in parallel rather than sequentially, significantly reducing the total execution time for OSINT investigations.