Setting Up Python: Installing Python 3, pip, venv, VS Code or PyCharm and a Clean Project Layout

Key takeaways

Install Python 3 on Windows, macOS or Linux, give every project its own virtual environment, point VS Code or PyCharm at it, and avoid the classic setup errors: the Microsoft Store python alias, externally-managed-environment, and pip installing into a different interpreter than the one running your code.

Introduction: Start coding in Python

Installing Python takes a few minutes. Most beginner problems come later and have the same root cause: there are several Python interpreters on the machine, and the one that runs your code is not the one that pip installed packages into. This guide installs Python on Windows, macOS and Linux, then sets up the habits that prevent that problem: a virtual environment per project, python -m pip instead of bare pip, and an editor pointed at the right interpreter.

You will learn:

  • Installing Python (official installer, Homebrew, distribution packages, pyenv)
  • pip, requirements.txt, and where Poetry and uv fit
  • Virtual environments with venv, and when conda is the better choice
  • Editors: VS Code and PyCharm
  • A practical layout: src/, tests/, .gitignore
  • The errors people hit first, and what they mean

Installing Python

Windows

  1. Download the latest Python 3 from python.org/downloads.
  2. Run the installer.
  3. Check “Add python.exe to PATH” so python and pip work in the terminal.
  4. Choose Install Now or customize paths if needed.
  5. Verify in a new terminal:
python --version
pip --version
py --version

If Python is not on PATH, add the install and Scripts directories (e.g. ...\Python312\ and ...\Python312\Scripts\) under Environment Variables → Path, then open a new terminal. Already-open terminals keep the old PATH, which is why “I fixed PATH and it still does not work” is so common.

Two Windows specifics save a lot of confusion. First, Windows ships “app execution aliases” for python.exe and python3.exe that open the Microsoft Store instead of running Python. If typing python opens the Store or prints nothing, turn those aliases off under Settings → Apps → Advanced app settings → App execution aliases, or use the py launcher, which the python.org installer adds. Second, py can pick a version explicitly: py -3.12 -m venv .venv creates an environment with Python 3.12 even when several versions are installed.

macOS (Homebrew)

brew install python
python3 --version
pip3 --version

On macOS, the commands are python3 and pip3; a plain python may not exist at all. Homebrew upgrades its Python when you run brew upgrade, which can move you to a new minor version (3.12 to 3.13) and break virtual environments created with the old one, since a venv refers to the interpreter it was created from. Recreating the venv fixes it. If you need a specific version to stay put, install it through pyenv (or uv) and record it in a .python-version file.

Linux (Debian/Ubuntu)

sudo apt update
sudo apt install python3 python3-pip python3-venv
python3 --version
pip3 --version

Distribution Python belongs to the operating system: system tools are written against it, and the distribution updates it. That is why recent Debian and Ubuntu releases refuse pip install outside a virtual environment with error: externally-managed-environment (see Common setup errors). Use a venv per project, and if you need a newer Python than the distribution provides, install it with pyenv or uv rather than replacing the system one.


pip

pip installs packages from PyPI, the Python Package Index.

python -m pip install requests
python -m pip install requests==2.28.0
python -m pip install --upgrade requests
python -m pip uninstall requests
python -m pip list
python -m pip show requests

python -m pip looks longer than pip, but it answers the question “which Python does this install into?” for you: the one you just named. A bare pip is whichever pip script comes first on PATH, and on a machine with two Pythons it can belong to the other one. That mismatch is the cause of most ModuleNotFoundError reports right after a “successful” install.

requirements.txt

python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt

Example:

requests==2.28.0
flask==2.3.0
pandas==2.0.0

pip freeze writes every package in the environment with its exact version, including dependencies of dependencies. Run it inside the project’s virtual environment, or the file lists everything ever installed globally. Exact pins make installs reproducible, but the file mixes the packages you chose with the ones they pulled in, which makes upgrades awkward. Tools such as pip-tools (requirements.in compiled to a pinned requirements.txt), Poetry and uv keep the two lists separate.

Poetry and uv (optional)

Poetry manages dependencies, virtual environments and a lock file through pyproject.toml and poetry.lock. Install it with pipx so it lives in its own environment, not inside a project:

pipx install poetry
poetry new my-package
cd my-package
poetry add requests
poetry install
poetry run python -m my_package

Older tutorials end with poetry shell. Poetry 2.0 moved that command into a separate plugin; poetry run <command> works everywhere, and poetry env activate prints the command that activates the environment.

uv is a newer, very fast tool that covers pip, venv, pip-tools and Python version installation in one binary (uv venv, uv pip install, uv add, uv python install 3.12). For a beginner, plain venv and pip are enough to learn the concepts; teams that want lock files and speed often standardize on uv or Poetry. pip vs uv vs Poetry compares them.


Virtual environments

A virtual environment is a directory containing its own python executable (a link or copy of the base interpreter) and its own site-packages folder for installed libraries. Activating it just puts that directory’s bin (or Scripts on Windows) first on PATH, so python and pip refer to it.

Why: project A needs Django 4 and project B needs Django 5; both can coexist. Just as important, your system Python stays clean, and deleting a project’s environment removes exactly what that project installed.

Create and activate (venv)

# Windows (PowerShell)
python -m venv .venv
.venv\Scripts\Activate.ps1
# macOS / Linux
python3 -m venv .venv
source .venv/bin/activate

When active, your prompt usually shows (.venv). Then python -m pip install affects only this environment.

deactivate

Naming the directory .venv has two small advantages over venv: VS Code and many other tools detect it automatically, and the leading dot keeps it out of the way in file listings. Activation is a convenience, not a requirement. .venv/bin/python script.py (or .venv\Scripts\python.exe script.py) uses the environment without activating anything, which is how cron jobs, services and CI usually run it.

A venv is not portable. It contains absolute paths to the interpreter it was created from, so moving or renaming the project folder, copying it to another machine, or upgrading the base Python breaks it, often with errors like No such file or directory pointing at the old path. Do not commit it and do not copy it; delete it and recreate it from requirements.txt.

Typical workflow

mkdir my_project && cd my_project
python -m venv .venv
source .venv/bin/activate   # or the Windows activate script
python -m pip install --upgrade pip
python -m pip install flask requests
python -m pip freeze > requirements.txt
deactivate

conda (Anaconda/Miniconda) is strong when you need non-Python binaries and scientific stacks aligned in one toolchain.

conda create -n myenv python=3.12
conda activate myenv

Rule of thumb: web and general apps → venv + pip; heavy data/GPU stacks with compiled libraries → consider conda. Conda environments are a different mechanism from venv, and installing packages into one with pip is possible but can leave conda unaware of them, so a later conda install may overwrite or conflict with them. Prefer conda install for everything available on conda channels, and pip only for the rest.


VS Code

  1. Install from code.visualstudio.com.
  2. Install the Python extension (Microsoft; Pylance comes with it).
  3. Run Python: Select Interpreter from the Command Palette and choose ./.venv/.... The selected interpreter appears in the status bar.

Recommended settings (excerpt):

{
  "editor.formatOnSave": true,
  "python.terminal.activateEnvironment": true,
  "python.analysis.typeCheckingMode": "basic"
}

Install Ruff or Black in your venv for formatting, together with the matching VS Code extension.

The interpreter selection is what everything else depends on: the Run button, the debugger, the terminal activation and Pylance’s “Import could not be resolved” warnings all use it. If VS Code underlines an import you just installed, the package is almost always in a different environment from the one selected. Also note that a terminal opened before you selected the interpreter is not activated; open a new one.


PyCharm

PyCharm is a full IDE: refactoring, debugger, test runner and database tools. When creating a project, choose a new virtualenv (or Poetry/uv/conda) interpreter; for an existing folder, set it under Settings → Project → Python Interpreter. That setting plays the same role as VS Code’s interpreter selection: packages installed through PyCharm’s interpreter panel go into that environment, and the Run configurations use it.


Project layout

my_project/
├── src/
│   └── my_package/
│       ├── __init__.py
│       └── main.py
├── tests/
│   └── test_main.py
├── pyproject.toml
├── requirements.txt
├── README.md
├── .gitignore
└── .venv/          # not committed
  • src/: the package lives one level down, so tests cannot accidentally import it from the project root; they import the installed version (python -m pip install -e .), which is what users get.
  • tests/: run with pytest.
  • .gitignore: ignore .venv/, __pycache__/, .env, IDE folders.

For a first script or a small exercise, this is more structure than you need; a single folder with main.py and a .venv is fine. The layout pays off once there are several modules and tests. A common beginner error with it is running python src/my_package/main.py directly and getting ModuleNotFoundError: No module named 'my_package' for imports between modules; install the package in editable mode and run it as python -m my_package.main instead.


Your first program

REPL

python
>>> print("Hello, Python!")
>>> exit()

Script file

# hello.py
import sys

print("Hello, Python!")
print(sys.version)
print(sys.executable)   # which interpreter is running this file
name = "Alice"
print(f"Hello, {name}")
python hello.py

sys.executable is worth keeping in a scratch script. When a package seems installed but cannot be imported, printing it shows which interpreter is actually running, and comparing it with python -m pip --version (which prints the path of the environment pip belongs to) usually solves the mystery in a minute.

VS Code

Open hello.py, use Run Python File in Terminal or F5 for debugging. Set breakpoints in the gutter.


Common setup errors

SymptomCauseFix
python opens the Microsoft Store or is “not recognized”App execution alias, or PATH not setDisable the aliases, reinstall with “Add to PATH”, or use py
error: externally-managed-environmentpip run against the OS-managed PythonCreate and activate a venv; use pipx for CLI tools
ModuleNotFoundError right after pip installpip and python belong to different interpreterspython -m pip install ...; check sys.executable and the editor’s selected interpreter
Activate.ps1 cannot be loaded because running scripts is disabledPowerShell execution policySet-ExecutionPolicy -Scope CurrentUser RemoteSigned, or use activate.bat from cmd
SSL: CERTIFICATE_VERIFY_FAILED on pip installCorporate proxy with its own certificateConfigure the proxy and point pip at the company CA (pip config set global.cert path/to/ca.pem)
venv broken after moving the folder or upgrading Pythonvenv stores absolute paths to its base interpreterDelete .venv, recreate, pip install -r requirements.txt

The externally-managed error deserves one more sentence, because the error message itself offers --break-system-packages as an option. That flag does what it says: it lets pip overwrite packages that the operating system’s own tools depend on, and a later apt upgrade may then fail or undo your changes. On a personal machine it is rarely worth it; a venv takes one command.

For SSL errors, you will find advice to add --trusted-host pypi.org --trusted-host files.pythonhosted.org. That disables certificate verification for those hosts, which is exactly the protection a man-in-the-middle proxy would need you to turn off. Fixing the certificate configuration is the safer route.

I would put the interpreter-mismatch row first if the table were sorted by frequency. It is almost always the same story: pip on PATH belongs to one Python, the editor or python command uses another, and the fix is to stop relying on bare pip.


Hands-on example

Simple calculator (calculator.py)

def add(a, b):
    """Add two numbers."""
    return a + b
def subtract(a, b):
    return a - b
def multiply(a, b):
    return a * b
def divide(a, b):
    if b == 0:
        return "Error: division by zero"
    return a / b
def main():
    print("=" * 40)
    print("Simple calculator")
    print("=" * 40)
    num1 = float(input("First number: "))
    op = input("Operator (+, -, *, /): ")
    num2 = float(input("Second number: "))
    if op == "+":
        result = add(num1, num2)
    elif op == "-":
        result = subtract(num1, num2)
    elif op == "*":
        result = multiply(num1, num2)
    elif op == "/":
        result = divide(num1, num2)
    else:
        result = "Invalid operator"
    print(f"\nResult: {num1} {op} {num2} = {result}")
if __name__ == "__main__":
    main()

This is a first-day program, so two shortcuts are deliberate. Typing abc at the first prompt crashes it with ValueError: could not convert string to float: 'abc', which is a good moment to learn try/except. And divide returns a string for an error but a number otherwise; in real code, raising an exception (raise ZeroDivisionError(...)) keeps the return type consistent, and the caller decides how to report it. The if __name__ == "__main__": line means main() runs when you execute the file but not when another file imports it.

Sample .gitignore

venv/
.venv/
__pycache__/
*.pyc
.env
.idea/

Advanced pointers

  • pyenv (or uv python install): install and switch between several Python versions per project.
  • Docker: FROM python:3.12-slim, COPY requirements.txt, RUN pip install --no-cache-dir -r requirements.txt. The image is already isolated, so a venv inside it is optional.
  • CI: GitHub Actions actions/setup-python with a matrix of Python versions.

Summary

  1. Install a supported Python 3 from python.org or a package manager; on Windows, make sure PATH is set and the Store aliases are not in the way.
  2. Create a .venv per project and install packages into it with python -m pip.
  3. Keep dependencies in requirements.txt (or let Poetry or uv manage a lock file).
  4. Point VS Code or PyCharm at the project’s venv.
  5. When an import fails, compare sys.executable with python -m pip --version.

Next steps


Official resources


Frequently Asked Questions (FAQ)

Q. Why does pip install succeed but import still raises ModuleNotFoundError?

A. The pip you ran belongs to a different interpreter than the python running your code, which is common with several Python versions or an inactive virtual environment. Run python -m pip install <package> with the same python you use to run the script, so both point to one environment. In VS Code, also check that the selected interpreter in the status bar is your project’s .venv, not the system Python.