A proper way of setting up Python on Linux
Python is preinstalled on most Linux systems — but you should not use the system Python for development.
Doing so often leads to broken system tools, conflicting dependencies, and unrepeatable environments.
This article shows a clean, professional setup used by experienced developers:
- Use pyenv to manage Python versions
- Install a modern global Python (example: 3.12.2)
- Use venv for project isolation
- Add small shell helpers that remove daily friction
The result: predictable Python, no system breakage, and zero guesswork.
Why not use the system Python?
Linux distributions rely on Python internally (package managers, desktop tools, installers).
Problems with system Python:
- Versions lag behind upstream
- Upgrading can break your OS
- Global
pip installcauses dependency conflicts
Rule:
System Python is for the OS. Your Python is for you.
Step 1: Install pyenv
pyenv lets you install and switch Python versions without touching the system Python.
Install dependencies (Ubuntu/Debian example)
sudo apt update
sudo apt install -y \
build-essential \
libssl-dev \
zlib1g-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
curl \
git \
libncursesw5-dev \
xz-utils \
tk-dev \
libxml2-dev \
libxmlsec1-dev \
libffi-dev \
liblzma-dev
Install pyenv
curl https://pyenv.run | bash
Add this to ~/.bashrc (or ~/.zshrc):
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
Reload your shell:
exec $SHELL
Verify:
pyenv --version
Step 2: Install a modern global Python (3.12.2)
List available versions:
pyenv install --list
Install Python 3.12.2:
pyenv install 3.12.2
Set it as your global default:
pyenv global 3.12.2
Verify:
python --version
which python
You should see something like:
Python 3.12.2
~/.pyenv/shims/python
✔ This confirms pyenv is in control.
Step 3: Ensure venv support
Modern Python ships with venv built-in. Verify:
python -m venv --help
If that works, you’re ready.
Step 4: Create a venv() helper function
Typing the same commands repeatedly is pointless.
Add this function to your ~/.bashrc:
function venv() {
echo "Setting up and activating venv in current directory"
python -m venv venv
source venv/bin/activate
pip install --upgrade pip
python --version
}
Usage
From any project directory:
venv
What this does:
- Creates a
./venvdirectory - Activates it
- Upgrades
pipimmediately
No thinking required.
Step 5: Auto-activate venv when entering a directory
This is a huge quality-of-life improvement.
Add this override to ~/.bashrc:
function cd() {
# We should recognize both .venv and venv as environments
# Deactivate old venv if needed
if [[ -n "$VIRTUAL_ENV" && -d ./venv ]]; then
if declare -F deactivate >/dev/null; then
deactivate
fi
fi
builtin cd "$@"
# Activate new venv if it exists
if [[ -d ./.venv ]]; then
echo "Activating virtual environment in ./.venv..."
. ./.venv/bin/activate
fi
if [[ -d ./venv ]]; then
echo "Activating virtual environment in ./venv..."
. ./venv/bin/activate
fi
}
Result
cd project/→ venv activates automaticallycd ..→ venv deactivates naturally- No manual
sourcecommands ever again
This mirrors professional workflows used in large Python codebases.
Recommended daily workflow
mkdir myproject
cd myproject
venv
pip install requests
Next time:
cd myproject
# venv auto-activates
Clean. Predictable. Repeatable.
Summary
This setup gives you:
✔ No system Python breakage
✔ One clean global Python version
✔ Isolated project environments
✔ Zero friction in daily use
pyenv + venv + small shell helpers is the correct way to run Python on Linux.
Once you use this approach, you’ll never go back.
Using this setup with VS Code
VS Code works very well with pyenv and venv, as long as you point it at the correct interpreter. First, install the official Python extension from Microsoft. Then open your project folder in VS Code after the virtual environment has been created. Press Ctrl + Shift + P, select “Python: Select Interpreter”, and choose the interpreter located inside your project, typically ./venv/bin/python. VS Code will remember this choice per workspace and automatically use the correct Python, pip, and installed packages for linting, testing, and debugging. If you use the terminal inside VS Code, it will usually activate the same virtual environment automatically, matching your shell behavior.
The key rule is simple:
- always select the interpreter inside your project’s venv
- never the system Python
- never the bare pyenv global interpreter.
Common VS Code mistakes (and how to avoid them)
A very common mistake is letting VS Code auto-select the system Python or the pyenv global Python instead of your project’s virtual environment. If you see import errors or missing packages in VS Code but everything works in the terminal, this is almost always the reason. Another mistake is opening VS Code before creating the venv — VS Code will then lock onto the wrong interpreter and keep using it until you manually change it. Finally, avoid running pip install without checking which interpreter VS Code is using; always confirm that ./venv/bin/python is selected.
VS Code checklist for new projects
Use this checklist every time you start a new Python project:
- Create the project directory and
cdinto it - Run
venvto create and activate the virtual environment - Open the folder in VS Code after the venv exists
- Press Ctrl + Shift + P → Python: Select Interpreter
- Select
./venv/bin/python - Open the VS Code terminal and confirm
(venv)is visible
If all of the above are true, VS Code, your shell, and Python are now perfectly aligned.
Why VS Code sometimes gets Python wrong
VS Code does not actually “understand” Python environments — it guesses based on what it sees when a folder is opened. If no virtual environment exists yet, VS Code will scan your system and often pick the first Python it finds in PATH, which may be the system Python or a pyenv shim. Once that choice is made, it is cached in the workspace settings and reused, even if you later create a venv. This is why opening VS Code after creating the virtual environment is so important. Selecting the interpreter manually forces VS Code to bind all Python-related features (linting, IntelliSense, debugging, testing, terminal) to the correct interpreter, ensuring that what you run, what you edit, and what you install are all using the same Python.