Course 0W · Module 3 Environment Variables, PATH & Software Installation
Python for Actuarial Students · Course 0W
Module 3

Environment Variables, the System PATH & Software Installation

How Windows finds programs, why “not recognized” happens, and how to install software the programmer’s way with winget.

Module 3 · OverviewBy the end of this module you can…

  • Describe what happens between typing a command and it running
  • Explain environment variables and read them with $env:
  • Read, edit, and repair your PATH — GUI and PowerShell
  • Tell user variables from system variables
  • Diagnose “is not recognized” errors methodically
  • Recognize executable types and set a sensible execution policy
  • Install software with installers and with winget
50 min
Concepts & demos
35 min
Build your own global command
Part 1

How Windows Finds Programs

You type python. What actually happens?

The lookupWhat happens when you press Enter

1. Built-in?Is python a PowerShell alias, function, or cmdlet?
no →
2. Search PATHLook in each folder listed in PATH, in order
→
3. Try extensionsIn each folder try python.exe, .cmd, .bat, .ps1…
→
4. First hit winsRun it. Stop searching.

Nothing found in any folder?
python: The term 'python' is not recognized as a name of a cmdlet, function, script file, or executable program.

PowerShell does not look in the current folder. To run build.ps1 sitting right here, type .\build.ps1.

ConceptEnvironment variables

Named text values that every program inherits when it starts — shared settings for the whole session.

PS> $env:USERNAME
Jane
PS> $env:USERPROFILE
C:\Users\Jane
PS> ls env:          # list them all
VariableTypical value
USERPROFILEC:\Users\Jane
APPDATA…\AppData\Roaming
LOCALAPPDATA…\AppData\Local
TEMP…\AppData\Local\Temp
COMPUTERNAMELAPTOP-7F3K
PATHthe list of program folders

Syntax differs by shell: $env:TEMP in PowerShell, %TEMP% in cmd & Explorer, os.environ["TEMP"] in Python.

ConceptPATH: the phone book for programs

One long string of folders separated by ;

Windows reads it top to bottom and runs the first match.

Split it into lines to make it readable:
$env:PATH -split ';'

PS> $env:PATH -split ';'
C:\Program Files\PowerShell\7
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\System32\WindowsPowerShell\v1.0\
C:\Program Files\Git\cmd
C:\Users\Jane\.local\bin
C:\Users\Jane\AppData\Local\Microsoft\WindowsApps
C:\Users\Jane\AppData\Local\Programs\Microsoft VS Code\bin

ConceptOrder matters: the case of the fake python

Fresh Windows installs contain a stub python.exe in WindowsApps that just opens the Microsoft Store.

Ask PowerShell which one wins:

PS> Get-Command python -All | Select-Object Source

Source
------
C:\Users\Jane\AppData\Local\Microsoft\WindowsApps\python.exe

where.exe python does the same job and works in cmd too.

Get-Command answers the question “which program will actually run?” — the first thing to check whenever a tool behaves strangely.

Turn the stub off: Settings → Apps → Advanced app settings → App execution aliases → switch off python.exe and python3.exe. In Module 4, uv will give us real Pythons.

ScopeUser variables vs. system variables

User variables

  • Apply only to you
  • Edit without admin rights
  • Where per-user tools (uv, VS Code) add themselves
  • This is where we work.

System variables

  • Apply to every user on the PC
  • Require administrator rights
  • Where machine-wide installs (Git, Windows) live
  • Look, don’t touch.
System PATH
+
User PATH
=
$env:PATHwhat each new terminal sees

LifetimeChanges only reach new windows

Each program copies the environment when it starts. After you change a variable permanently:

  • Terminals already open still have the old copy
  • VS Code (and its terminals) still has the old copy

Changed PATH? Close and reopen the terminal — every time.

Set with…Lasts
$env:X = "…"This terminal window only — gone when closed
Environment Variables dialogPermanent, all future programs
[Environment]::SetEnvironmentVariable(…, "User")Permanent, all future programs

EditingThe GUI way

  1. Press Win, type “environment”, choose Edit environment variables for your account (no admin needed)
  2. Top half = User variables. Select Path → Edit…
  3. New → paste a folder path → Move Up/Down to set priority
  4. OK, OK — then open a new terminal

Shortcuts that open the same dialog:

rundll32 sysdm.cpl,EditEnvironmentVariables

sysdm.cpl → Advanced tab → Environment Variables… (this route shows System variables too, which need admin to change)

Never paste over the whole Path value. Add or remove one entry at a time.

EditingThe PowerShell way

# Read
$env:PATH -split ';'
[Environment]::GetEnvironmentVariable("Path", "User") -split ';'   # just the User part

# Temporary — this window only (great for experiments)
$env:PATH = "C:\actuarial_work\bin;" + $env:PATH
$env:MY_DATA_DIR = "C:\actuarial_work\data"

# Permanent — append a folder to the USER Path
$bin      = "C:\actuarial_work\bin"
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
[Environment]::SetEnvironmentVariable("Path", "$userPath;$bin", "User")

The permanent version writes to the registry, exactly like the GUI. Run it once; running it twice adds the folder twice (harmless, but messy).

Troubleshooting“… is not recognized” — a diagnostic checklist

  1. Typo? Try Tab-completing the command name.
  2. Installed? Find the actual .exe on disk (installer docs, winget list).
  3. Which folder? Note the folder that contains it, e.g. C:\Users\Jane\.local\bin.
  4. On PATH? $env:PATH -split ';' — is that folder listed?
  5. Stale window? Open a new terminal and try again.
  6. Still no? Add the folder to your User Path and repeat step 5.
PS> uv --version
uv: The term 'uv' is not recognized…

PS> Test-Path ~\.local\bin\uv.exe
True
PS> $env:PATH -split ';' |
>>   Select-String local
(nothing)

Diagnosis: installed, but its folder isn’t on PATH in this window.

ExecutablesWhat counts as a “program”?

ExtensionWhat it isRun by
.exeCompiled program — python.exe, git.exe, uv.exeWindows directly
.cmd / .batBatch script — old-style command listcmd.exe
.ps1PowerShell scriptPowerShell — if execution policy allows
.pyPython scriptPython: python script.py / uv run script.py

The variable PATHEXT lists which extensions Windows tries automatically: $env:PATHEXT → .COM;.EXE;.BAT;.CMD;…

ExecutablesExecution policy: why your .ps1 won’t run

PS> .\mkproj.ps1
.\mkproj.ps1 cannot be loaded because running
scripts is disabled on this system.

Windows client PCs default to Restricted. The recommended setting for developers:

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Get-ExecutionPolicy -List      # verify
PolicyMeaning
RestrictedNo scripts at all
RemoteSignedYour own scripts run; downloaded scripts must be signed
UnrestrictedEverything runs (warns on downloads)
BypassNo checks — used for one-off commands

-Scope CurrentUser = no admin needed, affects only you. On managed work PCs, IT policy may override this.

Part 2

Installing Software

Point-and-click installers vs. the winget package manager.

InstallingTwo ways to install

Downloadable installer (.exe / .msi)

  • Find the official site, pick the right download
  • Click through a wizard — some screens matter (e.g. “Add to PATH”)
  • Updates: remember to come back
  • Easy to grab a fake from a search ad

Package manager (winget)

  • One command; built into Windows 10/11
  • Pulls from a curated catalog of official installers
  • winget upgrade --all updates everything
  • Scriptable — a whole setup in one file

Either way, most installers edit your PATH. That’s why this lives in the PATH module — and why you open a new terminal after every install.

wingetEveryday winget

winget search pandoc                  # find packages
winget show --id JohnMacFarlane.Pandoc   # details
winget install --id JohnMacFarlane.Pandoc -e
winget list                           # what's installed
winget upgrade                        # what's out of date
winget upgrade --all                  # update everything
winget uninstall --id JohnMacFarlane.Pandoc

IDs we’ll use in this course

Microsoft.PowerShell
astral-sh.uv
Git.Git
JohnMacFarlane.Pandoc
Microsoft.VisualStudioCode

--id … -e means “this exact ID”, avoiding look-alike packages. The first run may ask you to accept the source agreements — read, then type Y.

Hands-on Lab · 35 minBuild your own global command

Goal: type mkproj pricing_2026 from any folder and get a ready-made project skeleton.

  1. Create a personal script folder: C:\actuarial_work\bin
  2. Allow your own scripts to run (execution policy)
  3. Write the tiny utility mkproj.ps1
  4. Add the folder to your User PATH
  5. Open a new terminal and call it from anywhere

Lab · Steps 1–3Folder, policy, script

mkdir C:\actuarial_work\bin
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
notepad C:\actuarial_work\bin\mkproj.ps1        # say "Yes" to create the file

Type this into Notepad and save:

# mkproj.ps1 — create a standard actuarial project skeleton
param([Parameter(Mandatory)] [string] $Name)

$folders = "data", "notebooks", "src", "output", "tests"
foreach ($f in $folders) {
    New-Item -ItemType Directory -Force -Path (Join-Path $Name $f) | Out-Null
}
Write-Host "Created $Name with: $($folders -join ', ')" -ForegroundColor Green

Check with ls C:\actuarial_work\bin that it’s mkproj.ps1 — not mkproj.ps1.txt (Module 1 flashback!).

Lab · Steps 4–5Put it on the PATH and test

4 · Add to User PATH (pick one)

GUI: Edit environment variables for your account → Path → New → C:\actuarial_work\bin

PowerShell:

$bin = "C:\actuarial_work\bin"
$u = [Environment]::GetEnvironmentVariable("Path","User")
[Environment]::SetEnvironmentVariable("Path","$u;$bin","User")

5 · New terminal, then:

PS C:\Users\Jane> cd C:\actuarial_work
PS C:\actuarial_work> mkproj pricing_2026
Created pricing_2026 with: data, notebooks,
src, output, tests
PS C:\actuarial_work> Get-Command mkproj

CommandType  Name        Source
-----------  ----        ------
ExternalScript mkproj.ps1 C:\actuarial_work\bin\mkproj.ps1

Bonus: install something with winget (e.g. winget install --id JohnMacFarlane.Pandoc -e — we need it in Module 6), then find which PATH entry it added.

RecapModule 3 checklist

  • I can explain how a command name becomes a running program
  • I can list environment variables and print one with $env:NAME
  • I can read my PATH one entry per line
  • I know user vs. system variables, and I edit only user ones
  • After changing PATH or installing software, I open a new terminal
  • I can diagnose “not recognized” with Get-Command and Test-Path
  • My execution policy is RemoteSigned for CurrentUser
  • I can install, list, and upgrade software with winget
  • mkproj works from any folder
Up next
Module 4

Next-Gen Python Tooling with uv

Python itself, virtual environments, and reproducible packages — installed per-user, no admin, no PATH surgery.