Python, pip, and Virtual Environments: A Practical Linux Guide

Overview
Python virtual environments are one of those concepts that may seem unnecessary until the first time a Python tool refuses to run, a package cannot be found, or installing one dependency breaks something else. In cybersecurity labs, this happens frequently because many security tools, proof-of-concept scripts, automation projects, and utilities rely on Python packages that are not installed by default.
If you have ever encountered an error such as:
ModuleNotFoundError: No module named 'impacket'
the problem is not necessarily with the script. Python is telling you that the interpreter running the program cannot locate the required module.
The temptation is to immediately run:
pip install impacket
or, worse:
sudo pip install impacket
Modern Linux distributions make that approach increasingly problematic. Python packages installed globally can interfere with packages maintained by the operating system’s package manager. Virtual environments solve this problem by giving each project its own isolated Python environment.
This Field Guide explains Python package management, pip, virtual environments, requirements.txt, pipx, common errors, and a practical workflow that works well for cybersecurity labs.
What Is pip?
pip is Python’s package installer. It downloads and installs Python packages and their dependencies, normally from the Python Package Index (PyPI).
For example:
pip install requests
installs the Requests HTTP library into the Python environment associated with that particular pip command.
You can see the installed version of pip with:
pip --version
You may also encounter:
pip3 --version
On systems with multiple Python installations, I prefer being explicit about which interpreter should execute pip:
python3 -m pip --version
This tells Python 3 to execute the pip module associated with that interpreter.
Why This Matters
One of the most common sources of Python confusion is having multiple Python interpreters installed. The pip command you execute may not always belong to the same Python interpreter running your script.
Using:
python3 -m pip
makes that relationship explicit.
Installing pip on Debian, Ubuntu, and Kali Linux
Before using pip, verify whether it is already installed:
python3 -m pip --version
If it is unavailable on a Debian-based system, update the package information:
sudo apt update
Then install pip:
sudo apt install python3-pip
Virtual environment support may also need to be installed:
sudo apt install python3-venv
You can install both at once:
sudo apt install python3-pip python3-venv
Important:
aptandpipserve different purposes.aptmanages software packages maintained by the Linux distribution, whilepipmanages Python packages.
The Problem with Installing Everything Globally
Older tutorials frequently contain commands such as:
sudo pip install package-name
This should generally be avoided.
Linux distributions rely heavily on Python themselves. Installing or replacing Python libraries globally with pip can create conflicts between packages installed by pip and packages maintained by the operating system.
The result can become something like:
Linux Package Manager
|
v
System Python
|
+-- Distribution Package A
+-- Distribution Package B
+-- pip replaces dependency
|
v
Potential conflict
A better approach is to leave the operating system’s Python environment alone and create an isolated environment for your project.
The externally-managed-environment Error
On modern Debian-based distributions, you may encounter an error containing:
externally-managed-environment
This behavior is associated with PEP 668, which allows a Python installation to identify itself as externally managed.
In practical terms, your Linux distribution is saying:
This Python installation belongs to the operating system. Do not modify it indiscriminately with pip.
You may discover options online that bypass this protection. Unless you specifically understand why you need to modify the system Python environment, creating a virtual environment is usually the cleaner solution.
What Is a Python Virtual Environment?
A virtual environment is an isolated Python environment associated with a particular project.
Instead of installing every Python dependency globally, you can create something like:
~/projects/
├── port-scanner/
│ └── venv/
├── web-recon/
│ └── venv/
└── api-testing/
└── venv/
Each project can maintain its own packages.
For example:
System Python
|
+-- port-scanner
| └── venv
| └── packages
|
+-- web-recon
| └── venv
| └── packages
|
+-- api-testing
└── venv
└── packages
Changes inside one virtual environment do not normally affect the others.
This is particularly useful in cybersecurity because different tools may depend on different versions of the same Python libraries.
Creating a Python Virtual Environment
Start by creating a directory for the project:
mkdir python-project
Move into it:
cd python-project
Now create the virtual environment:
python3 -m venv venv
Command Breakdown
| Component | Purpose |
|---|---|
python3 | Runs the Python 3 interpreter |
-m | Executes a Python module |
venv | Python’s virtual environment module |
venv | Directory where the environment will be created |
There is nothing special about naming the directory venv. You may also see:
python3 -m venv .venv
I like .venv because it clearly identifies the directory as the project’s virtual environment while keeping it less prominent in normal directory listings.
For this guide, however, we’ll use:
python3 -m venv venv
After running the command, the project might look similar to:
python-project/
└── venv/
├── bin/
├── include/
├── lib/
└── pyvenv.cfg
Activating the Virtual Environment
Creating the environment does not automatically activate it.
On Linux, activate it with:
source venv/bin/activate
Your terminal prompt will typically change:
(venv) user@kali:~/python-project$
That (venv) is an important visual indicator.
It tells you that commands such as:
python
and:
pip
now refer to the virtual environment rather than the normal system environment.
[Screenshot – Python Virtual Environment Activated]
Verify Which Python You Are Using
You can confirm the active Python interpreter with:
which python
Inside the virtual environment, the result should point somewhere beneath your project directory, similar to:
/home/user/python-project/venv/bin/python
You can check pip the same way:
which pip
Again, it should point into:
venv/bin/
This is an excellent troubleshooting technique when Python packages appear to be installed but your program cannot find them.
Installing Packages Inside the Environment
Once the environment is active, packages can be installed without modifying the system Python installation.
For example:
pip install requests
You do not need:
sudo
The package belongs to your user-controlled virtual environment.
You can display installed packages with:
pip list
You can inspect a particular package with:
pip show requests
This can provide information including the installed version and installation location.
A Cybersecurity Example: Impacket
A common example in penetration-testing labs is Impacket.
You may attempt to execute a Python program and receive:
ModuleNotFoundError: No module named 'impacket'
Instead of immediately modifying system Python, create an environment:
mkdir impacket-lab
cd impacket-lab
python3 -m venv venv
source venv/bin/activate
Then install the required Python package inside that environment:
pip install impacket
Verify the installation:
pip show impacket
The important lesson isn’t simply how to install Impacket. It is understanding where the package was installed and which Python interpreter can access it.
That distinction becomes extremely important as your collection of Python-based security tools grows.
Understanding requirements.txt
Imagine building a Python security utility that requires several external packages. Installing them manually works on your computer, but somebody cloning the project has no idea what dependencies are required.
This is where a requirements file becomes useful.
You can capture the packages installed in the current environment with:
pip freeze
To save the output:
pip freeze > requirements.txt
The project might now look like:
python-project/
├── scanner.py
├── requirements.txt
└── venv/
Someone can then create a new environment and install the dependencies using:
pip install -r requirements.txt
Command Breakdown
| Component | Purpose |
|---|---|
pip | Python package installer |
install | Installs packages |
-r | Reads package requirements from a file |
requirements.txt | File containing the dependencies |
This makes Python projects considerably easier to reproduce.
Rebuilding a Virtual Environment
One of the advantages of virtual environments is that they are disposable.
Suppose something becomes badly broken inside:
venv/
If your dependencies are documented, you can delete the environment and recreate it rather than spending hours trying to repair it.
First deactivate it if necessary:
deactivate
Then remove the environment directory:
rm -rf venv
Warning:
rm -rfrecursively deletes the specified directory without normal interactive confirmation. Verify that you are deleting the correct directory before executing it.
Create a fresh environment:
python3 -m venv venv
Activate it:
source venv/bin/activate
Then reinstall the project’s dependencies:
pip install -r requirements.txt
You now have a clean environment.
Leaving a Virtual Environment
When you are finished working, run:
deactivate
The (venv) indicator should disappear from your terminal prompt.
You have not deleted anything.
You have simply returned your shell to the normal system environment.
To work on the project later:
cd python-project
source venv/bin/activate
Do Not Commit the Virtual Environment to Git
If you store your Python projects in Git, you generally should not commit the entire venv directory.
Instead, add it to:
.gitignore
For example:
venv/
If you use .venv:
.venv/
The virtual environment may contain many files and can easily be recreated from the project’s dependency information.
A cleaner repository looks like:
python-project/
├── .gitignore
├── scanner.py
└── requirements.txt
Someone cloning it can recreate the environment themselves.
pip vs. venv vs. pipx
These tools are related, but they solve different problems.
| Tool | Primary Purpose |
|---|---|
pip | Install Python packages |
venv | Create isolated Python environments |
pipx | Install Python command-line applications into isolated environments |
Use pip inside a virtual environment when developing a Python project or working with a script that requires dependencies.
Use venv when you want complete isolation for a project.
pipx is especially useful when you want to install a Python-based command-line application without manually managing its virtual environment.
This distinction is useful in cybersecurity because some Python packages are libraries you import into your own code, while others provide standalone command-line tools.
Troubleshooting: Package Installed but Still Not Found
Suppose you run:
pip install requests
and Python still reports:
ModuleNotFoundError: No module named 'requests'
Start by checking:
which python
Then:
which pip
Also check:
python --version
and:
pip --version
You are looking for mismatched environments.
Another useful test is:
python -m pip list
This asks the exact Python interpreter you are currently using to execute its associated pip module.
You can also test the import directly:
python -c "import requests; print(requests.__version__)"
If that succeeds, the interpreter can locate the package.
Troubleshooting: python3 -m venv Fails
If the virtual environment module is unavailable on Debian, Ubuntu, or Kali, install it through the operating system package manager:
sudo apt update
sudo apt install python3-venv
Then try again:
python3 -m venv venv
Troubleshooting: Permission Denied
If you find yourself needing:
sudo pip install
inside a virtual environment, stop and investigate why.
Check:
which pip
If the environment is active, it should point into your project’s venv/bin directory.
Also check ownership of the project:
ls -la
A virtual environment inside your home directory should normally be owned by your user account.
A Practical Cybersecurity Workflow
For small Python security projects, I use the following general workflow:
mkdir scanner-project
cd scanner-project
python3 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
pip install requests
pip freeze > requirements.txt
Now create your Python program:
nano scanner.py
When finished:
deactivate
The next time you return:
cd scanner-project
source venv/bin/activate
That small habit keeps Python projects separated and makes troubleshooting much easier.
Why Virtual Environments Matter in Cybersecurity
Cybersecurity work frequently involves downloading research tools, testing proof-of-concept code, writing custom utilities, interacting with APIs, analyzing network traffic, or automating repetitive tasks.
Python is everywhere in that ecosystem.
A security workstation may eventually contain dependencies for reconnaissance scripts, packet manipulation libraries, exploit-development tools, forensic utilities, API clients, Active Directory tools, and dozens of small projects you’ve written yourself.
Installing everything into one global Python environment eventually becomes difficult to maintain.
Virtual environments create boundaries.
A dependency required by a web reconnaissance project doesn’t need to affect your packet-analysis project. A lab requiring a particular library version doesn’t require changing your entire workstation.
More importantly, understanding environments makes Python errors easier to diagnose. Instead of blindly installing packages until a program starts working, you can determine exactly which Python interpreter is executing the program, which packages are available to it, and where those packages are installed.
Common Mistakes
| Mistake | Better Approach |
|---|---|
Running sudo pip install automatically | Use a virtual environment |
| Installing every package globally | Separate dependencies by project |
Forgetting to activate venv | Check your prompt and which python |
Assuming pip and python match | Verify with python -m pip |
Committing venv/ to Git | Add it to .gitignore |
| Forgetting dependencies | Maintain requirements.txt |
Deleting an unknown directory with rm -rf | Verify the path before deletion |
Ignoring externally-managed-environment warnings | Understand PEP 668 and use isolation |
Using sudo inside a normal user-owned venv | Check environment activation and ownership |
Useful Commands Cheat Sheet
| Task | Command |
|---|---|
| Check Python | python3 --version |
| Check pip | python3 -m pip --version |
| Install pip | sudo apt install python3-pip |
| Install venv support | sudo apt install python3-venv |
| Create environment | python3 -m venv venv |
| Activate environment | source venv/bin/activate |
| Show Python location | which python |
| Show pip location | which pip |
| Install package | pip install PACKAGE |
| List packages | pip list |
| Inspect package | pip show PACKAGE |
| Export dependencies | pip freeze > requirements.txt |
| Install dependencies | pip install -r requirements.txt |
| Leave environment | deactivate |
Lessons Learned
Python virtual environments initially seem like an extra step. In reality, they remove many of the problems that appear when Python projects begin accumulating dependencies.
The most important concept is that installing a Python package and running a Python program are related operations. If the pip performing the installation belongs to one Python environment while the interpreter running your program belongs to another, Python may legitimately report that the module does not exist.
Instead of responding to every missing-module error with sudo pip install, identify the Python environment first.
Once you get into the habit of running:
python3 -m venv venv
source venv/bin/activate
before starting a Python project, managing dependencies becomes much more predictable.
References
For additional technical information, see the official Python documentation for venv, the Python Packaging User Guide for package installation and virtual environments, PyPI for Python package information, and PEP 668 for the externally managed environment specification.
Key Takeaways
Main lesson: Keep project-specific Python dependencies isolated from the operating system’s Python installation whenever practical.
Important commands:
python3 -m venv venv
source venv/bin/activate
python -m pip install PACKAGE
pip freeze > requirements.txt
pip install -r requirements.txt
deactivate
Skills practiced: Python package management, Linux environment management, dependency isolation, troubleshooting Python modules, and creating reproducible Python projects.
Defensive considerations: Avoid modifying system Python unnecessarily, be cautious with packages and scripts obtained from untrusted sources, review dependencies before installing them, and avoid blindly executing installation instructions from unknown repositories.
Understanding pip and virtual environments isn’t just Python housekeeping. For anyone building cybersecurity tools or working through security labs, it is a fundamental part of maintaining a stable and repeatable workstation.
