Demystifying Frappe's Dual Virtual Environments| Sabbirz | Blog

Demystifying Frappe's Dual Virtual Environments

Understanding Virtual Environments in Frappe

Frappe Framework's Multiple Virtual Environments

When setting up a Frappe or ERPNext development environment, many developers start by creating a Python virtual environment to isolate dependencies. Inside that environment, we usually install Bench, which then helps us create and manage Frappe sites and apps.

virtual env for installing frappe

However, what often goes unnoticed is that Frappe itself creates another virtual environment inside your bench directory.

virtual env for frappe bench

This internal environment — located at:

frappe-bench/env/

— is where Frappe and all its required Python packages 📦 actually live and run.


Two Layers of Virtual Environments 🏗️

Let’s break this down clearly:

  1. Outer environment – the one you manually created to install Bench (for example using python3 -m venv venv or conda create ...).
    • Bench gets installed here.
    • You use it to run commands like bench start, bench new-site, etc.
  2. Inner environment – automatically created inside your bench folder when you initialize it (bench init frappe-bench).
    • This is the actual runtime environment for Frappe.
    • All framework-level dependencies such as frappe, redis, gunicorn, pymysql, etc. are installed here.

So when you’re running your Frappe apps, the Python interpreter that executes your code is not the outer environment — it’s the one under frappe-bench/env.


Why Your pip install Might Not Work as Expected ❌

A common source of confusion arises when developers install additional packages like this:

pip install requests

This command installs the package in your outer environment — the one where Bench was installed. But Frappe doesn’t use that environment when executing your apps.

That means when you later try to import your newly installed package from within a Frappe app, you might see an error like:

ModuleNotFoundError: No module named 'requests'

Even though you “installed” it, Frappe can’t find it — because it’s not in its own virtual environment.


The Correct Way: Using bench pip

To make sure packages are installed inside Frappe’s internal environment, always run:

bench pip install <package_name>

For example:

bench pip install requests

This ensures the package is installed inside frappe-bench/env, making it accessible to all your Frappe apps.

You can also use other familiar pip commands in the same way:

bench pip list
bench pip uninstall <package_name>
bench pip freeze

These commands behave exactly like normal pip, but target the Frappe environment managed by Bench.


Quick Verification 🕵️

You can verify the path of your active Python environment by running:

bench exec which python

or

bench console
>>> import sys
>>> print(sys.executable)

You’ll notice the path points to something like:

/home/username/frappe-bench/env/bin/python

That’s the interpreter where Frappe and all your bench-managed apps run.


Summary

Task Wrong Way ❌ (Installs in Outer Env) Correct Way ✅ (Installs in Frappe Env)
Install a Python package pip install requests bench pip install requests
List installed packages pip list bench pip list
Uninstall a package pip uninstall requests bench pip uninstall requests

By understanding this simple but crucial distinction, you’ll avoid a lot of “module not found” errors and keep your Frappe environment clean and consistent.


💡 Tip:

If you ever need to manage dependencies across multiple benches, each bench has its own isolated environment under its folder. So, bench pip install commands apply per bench, not system-wide.

Related posts