Skip to content

Fix: Python venv Using Wrong Python Version

FixDevs ·

Quick Answer

How to fix Python virtual environments using the wrong Python version — venv picking system Python instead of pyenv, specifying the interpreter path, and verifying the active environment.

The Error

You create a virtual environment expecting Python 3.11 but get 3.9 (or another version):

python -m venv .venv
source .venv/bin/activate
python --version
# Python 3.9.7  ← Expected 3.11

Or you install a package that requires Python 3.10+ but it fails:

ERROR: Package 'some-package' requires a different Python: 3.9.7 not in '>=3.10'

Or pyenv shows the right version but the venv still uses the system Python:

pyenv version
# 3.11.8 (set by /home/user/project/.python-version)

python -m venv .venv
source .venv/bin/activate
python --version
# Python 3.9.18  ← Still wrong

Or after activating the venv, which python points outside the venv:

which python
# /usr/bin/python3  ← Should be /home/user/project/.venv/bin/python

Why This Happens

Virtual environments are created using whichever Python binary runs python -m venv. The resulting environment is permanently tied to that specific Python binary:

  • python command resolves to the wrong binarypython may point to Python 3.9 while python3 or python3.11 points to a newer version.
  • pyenv shims not in PATH or not initialized — pyenv works by inserting shims at the beginning of PATH. If pyenv’s init isn’t in your shell profile, the shims don’t activate and the system Python is used instead.
  • Shell profile not reloaded — you installed a new Python version but haven’t restarted your shell or run source ~/.bashrc.
  • python -m venv called before activating pyenv — if you run python -m venv .venv in a script or CI pipeline without first sourcing pyenv, it uses the system Python.
  • Conda base environment active — Conda’s base environment may intercept python and return its own version, regardless of pyenv settings.
  • venv already created with the wrong Python — once a venv is created, its Python version is fixed. Deleting and recreating is the only way to change it.

Fix 1: Specify the Python Binary Explicitly

The most reliable fix is to call the exact Python binary you want when creating the venv:

# Use the full path to the desired Python
/usr/bin/python3.11 -m venv .venv

# Or use the versioned command directly
python3.11 -m venv .venv
python3.10 -m venv .venv

# Verify the result
source .venv/bin/activate
python --version  # Should now show the correct version

Find available Python binaries:

# List Python binaries on the system
ls /usr/bin/python*
ls /usr/local/bin/python*

# Use 'which' to find a specific version
which python3.11
which python3.12

Fix 2: Fix pyenv Not Working

If you use pyenv but the venv still uses the system Python, fix the pyenv initialization:

# Check if pyenv is properly initialized
pyenv version
# If this fails or shows 'system', pyenv is not active

# Check if pyenv shims are in PATH
echo $PATH | tr ':' '\n' | grep pyenv
# Should see something like: /home/user/.pyenv/shims

# Initialize pyenv in your shell profile
cat ~/.bashrc  # or ~/.zshrc, ~/.bash_profile
# Should contain:
# export PYENV_ROOT="$HOME/.pyenv"
# export PATH="$PYENV_ROOT/bin:$PATH"
# eval "$(pyenv init -)"

Add pyenv initialization to your shell profile:

# For bash — add to ~/.bashrc or ~/.bash_profile
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc

# For zsh — add to ~/.zshrc
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
source ~/.zshrc

After initializing pyenv, verify it works:

# Verify pyenv is active
pyenv version
# 3.11.8 (set by /home/user/project/.python-version)

# Check which python pyenv resolves to
pyenv which python
# /home/user/.pyenv/versions/3.11.8/bin/python

# Now create the venv — it will use pyenv's Python
python -m venv .venv
source .venv/bin/activate
python --version
# Python 3.11.8 ✓

Install the Python version you need with pyenv:

# List available versions
pyenv install --list | grep "3.11"

# Install a specific version
pyenv install 3.11.8

# Set it globally (all projects)
pyenv global 3.11.8

# Set it for the current project only (creates .python-version file)
pyenv local 3.11.8

# Verify
python --version  # 3.11.8

Fix 3: Delete and Recreate the venv

Once a venv is created, its Python version is baked in and cannot be changed. Delete and recreate it with the correct Python:

# Deactivate the current venv if active
deactivate

# Delete the venv
rm -rf .venv

# Recreate with the correct Python
python3.11 -m venv .venv

# Or with pyenv active:
pyenv local 3.11.8
python -m venv .venv

# Activate and verify
source .venv/bin/activate
python --version
# Python 3.11.8 ✓

# Reinstall dependencies
pip install -r requirements.txt

Fix 4: Fix the PATH Order

If multiple Python installations conflict, PATH order determines which python command is found first:

# See the full resolution order
echo $PATH | tr ':' '\n'

# See which python is found
which python
which python3
which python3.11

# If pyenv shims aren't first, fix PATH order
# pyenv shims must come before /usr/bin
export PATH="$HOME/.pyenv/shims:$HOME/.pyenv/bin:$PATH"

Check for Conda interference:

# If Conda is active, it prepends its bin directory to PATH
conda info
# Shows: active environment

# Deactivate Conda base environment
conda deactivate

# Or configure Conda to not activate base by default
conda config --set auto_activate_base false

macOS — Homebrew Python conflicts:

# Homebrew installs Python at:
ls /opt/homebrew/bin/python*    # Apple Silicon
ls /usr/local/bin/python*       # Intel

# Set up PATH to prefer pyenv over Homebrew
# In ~/.zshrc:
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"    # pyenv first
eval "$(pyenv init -)"
# Homebrew's python3 comes after pyenv in PATH

Fix 5: Verify the Active venv

After activating a venv, verify all Python-related commands resolve inside the venv:

source .venv/bin/activate

# All of these should point inside .venv/
which python
# /home/user/project/.venv/bin/python

which pip
# /home/user/project/.venv/bin/pip

python --version
# Python 3.11.8

pip --version
# pip 23.x.x from /home/user/project/.venv/lib/python3.11/site-packages/pip (python 3.11)

# Confirm the venv's Python binary and its version
python -c "import sys; print(sys.executable, sys.version)"
# /home/user/project/.venv/bin/python 3.11.8 (...)

Check if the venv is actually active:

# The VIRTUAL_ENV environment variable is set when a venv is active
echo $VIRTUAL_ENV
# /home/user/project/.venv  ← Active
# (empty) ← Not active

# The prompt usually shows the venv name
# (.venv) user@host:~/project$ ← Active

Fix 6: Use python -m venv with a Specific Version in CI/CD

In CI/CD pipelines, always specify the exact Python version to avoid using whatever is installed by default:

# GitHub Actions
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'   # Exact version — not 'python3' or '3.x'

      - name: Create venv
        run: python -m venv .venv  # Uses the Python set by setup-python

      - name: Install dependencies
        run: |
          source .venv/bin/activate
          pip install -r requirements.txt
# GitLab CI
test:
  image: python:3.11-slim   # Pin the Python version in the Docker image
  script:
    - python --version       # Verify
    - python -m venv .venv
    - source .venv/bin/activate
    - pip install -r requirements.txt

In Docker:

# Pin the exact Python version in the base image
FROM python:3.11.8-slim

# This sets the default python command to 3.11.8
RUN python --version  # Python 3.11.8

WORKDIR /app
COPY requirements.txt .
RUN python -m venv .venv && \
    .venv/bin/pip install --no-cache-dir -r requirements.txt

# Use the venv's Python explicitly
CMD [".venv/bin/python", "app.py"]

Fix 7: Use Poetry or uv for Automatic Version Management

Modern Python package managers handle Python version selection automatically:

Poetry:

# pyproject.toml — specify Python version constraint
[tool.poetry.dependencies]
python = "^3.11"   # Requires Python 3.11 or higher
# Poetry creates the venv with a compatible Python
poetry env use python3.11  # Explicitly set the Python version
poetry env info             # Shows which Python Poetry is using

uv (modern, fast Python package manager):

# uv automatically finds and uses the right Python
uv venv --python 3.11 .venv        # Create venv with Python 3.11
uv venv --python /path/to/python   # Or use a specific binary

# Or in pyproject.toml
# [project]
# requires-python = ">=3.11"
# Then:
uv venv    # uv selects a compatible Python automatically

Still Not Working?

Check if the venv’s pyvenv.cfg shows the right version:

cat .venv/pyvenv.cfg
# home = /usr/bin           ← Where the Python was found (wrong if not 3.11)
# version = 3.9.7           ← The Python version (wrong)
# version_info = 3.9.7.final.0

If it shows the wrong version, the venv must be recreated.

Check for a .python-version file in a parent directory — pyenv reads .python-version from the current directory up to the root. A .python-version in a parent directory may override your local settings:

# Find all .python-version files from current dir upward
ls -la .python-version 2>/dev/null || echo "Not here"
ls -la ../.python-version 2>/dev/null || echo "Not in parent"

# The effective pyenv version
pyenv version
# Shows which .python-version file is controlling the version

Restart your shell after modifying shell profile files. Changes to ~/.bashrc, ~/.zshrc, or ~/.bash_profile don’t take effect until you start a new shell session or run source ~/.bashrc.

For related Python environment issues, see Fix: Python ModuleNotFoundError (venv) and Fix: pip No Matching Distribution Found.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles