Tutorial · Dependencies · Python

How to Auto-Install Python Packages in a Trading Bot

Published May 20, 2026 · 10 min read · By WatchDog Bot Team

Your bot worked perfectly on your laptop. You deployed it to a server, ran it, and got: ModuleNotFoundError: No module named 'ccxt'. This guide covers six ways to fix it — from the obvious pip install to a system that installs missing packages automatically inside an isolated environment so this never happens again.

What we'll cover

  1. Why ModuleNotFoundError keeps happening
  2. Fix 1: pip install (and why it's not enough)
  3. Fix 2: Use a virtual environment per bot
  4. Fix 3: Pin everything in requirements.txt
  5. Fix 4: Auto-install at runtime (with caveats)
  6. Fix 5: Use uv for fast, isolated installs
  7. Fix 6: A self-healing bot runtime
  8. Bonus: Common import-name mismatches

01Why ModuleNotFoundError keeps happening

Python's import system trusts the active environment to have every package your code uses. If something is missing, Python doesn't try to fix it — it raises ModuleNotFoundError and your process dies.

The reason this hits trading bots harder than most other Python code:

02Fix 1: pip install (and why it's not enough)

The naive fix:

pip install ccxt

This works for the immediate error. But it installs the package globally for that Python interpreter. Three problems:

This is the OK first step, but not where you should stop.

03Fix 2: Use a virtual environment per bot

One venv per bot solves the version-conflict problem:

# Create a venv for this bot
python -m venv .venv-mybot

# Activate it (macOS/Linux)
source .venv-mybot/bin/activate

# Or on Windows:
# .venv-mybot\Scripts\activate

# Install what you need
pip install ccxt pandas numpy

Now run your bot using that venv's Python:

.venv-mybot/bin/python my_bot.py

This works. The downsides:

04Fix 3: Pin everything in requirements.txt

For every bot, maintain a requirements.txt with explicit versions:

# requirements.txt
ccxt==4.2.5
pandas==2.1.0
numpy==1.26.0
requests==2.31.0

Then for any deploy:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

This is the textbook answer and works reliably. But it requires discipline. The reality of trading bot development is: you add an import to your code at 2 AM, you don't update requirements.txt, you push to production, it breaks. Every time.

05Fix 4: Auto-install at runtime (with caveats)

You can have your bot install its own dependencies on first run:

import importlib, subprocess, sys

def ensure(pkg, import_name=None):
    try:
        importlib.import_module(import_name or pkg)
    except ImportError:
        subprocess.check_call([sys.executable, "-m", "pip", "install", pkg])
        importlib.import_module(import_name or pkg)

ensure("ccxt")
ensure("pandas")

import ccxt, pandas  # now safe

Caveats: This pattern works but has rough edges. If a package fails to install (network error, wheel doesn't build), the bot crashes on startup. You're also installing into whichever venv is active — same scoping problems as fix #1. Worth using as a last resort or for the dev loop, not for production.

06Fix 5: Use uv for fast, isolated installs

uv is a fast Python package installer from Astral (the Ruff team) — written in Rust, 10–100× faster than pip. It also has built-in venv creation:

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Create a venv + install in one shot
uv venv .venv-mybot
uv pip install --python .venv-mybot/bin/python ccxt pandas

# Or even simpler: uv run handles venv+install+execute
uv run --with ccxt --with pandas python my_bot.py

uv run is the cleanest workflow we've seen for one-off bot execution. It creates an ephemeral environment, installs the packages, and runs your script. No requirements.txt to maintain.

The catch: you still have to declare every package you need, every time. If you add a new import to your code, you have to remember to pass --with new_package.

07Fix 6: A self-healing bot runtime

The pattern we landed on after building hundreds of bots: have the runtime watch the bot process, parse ModuleNotFoundError from its output, install the missing package, and restart. Automatically.

Conceptually:

import re, subprocess

MAX_RETRIES = 3
MISSING_PATTERN = re.compile(r"No module named ['\"]([\w\.]+)['\"]")

def run_with_self_heal(bot_script, bot_venv):
    for attempt in range(MAX_RETRIES):
        result = subprocess.run(
            [f"{bot_venv}/bin/python", bot_script],
            capture_output=True, text=True
        )
        if result.returncode == 0:
            return True
        m = MISSING_PATTERN.search(result.stderr)
        if not m:
            print(result.stderr)
            return False
        missing = m.group(1).split(".")[0]  # top-level package
        print(f"[self-heal] installing {missing}")
        subprocess.check_call([
            "uv", "pip", "install",
            "--python", f"{bot_venv}/bin/python",
            missing
        ])
    return False

This is exactly the pattern WatchDog Bot uses internally. Every bot gets its own uv-managed venv. When the bot raises ModuleNotFoundError, the runtime parses the missing module name, runs uv pip install into that bot's venv, and restarts the process. Up to 3 tries. Persistent — the runtime keeps a record so the next launch starts cleanly.

The user sees: their bot just works. No pip install, no requirements.txt, no remembering which venv to activate. They paste code with import ccxt, click Start, and the platform handles the rest.

One important guardrail: auto-install is great for well-known packages, but it can fail or take a long time for native-compiled dependencies. WatchDog Bot's runtime keeps a denylist (setuptools, wheel, pip itself) and a sanity check on package names so a malicious bot can't ask the platform to install something dangerous.

08Bonus: Common import-name mismatches

One reason auto-install systems trip up: the import name often differs from the PyPI package name. Some classics:

import statementpip install command
import cv2pip install opencv-python
import yamlpip install PyYAML
import PILpip install Pillow
import sklearnpip install scikit-learn
import bs4pip install beautifulsoup4
import dotenvpip install python-dotenv
import jwtpip install PyJWT
import dateutilpip install python-dateutil
import OpenSSLpip install pyOpenSSL
import google.cloudpip install google-cloud-storage

A naive auto-installer will try pip install cv2 and fail. Any production-grade auto-install system maintains a mapping table for the common cases. (Yes, WatchDog Bot does.)

The best dependency management is the dependency management you don't have to think about.

Skip the dependency rabbit hole

WatchDog Bot auto-installs every package your bot needs, in an isolated venv, with retry-on-failure. Free trial, no credit card.

Start Free Trial →

Related reading