Setting PYTHONPATH, concepts of namespace and scope; concepts of packages in Python

A namespace maps names to objects, scope decides which namespace a name resolves in (the LEGB order), packages group modules into folders, and PYTHONPATH tells Python where to hunt for them.

9 min read · 10 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

Two totals, zero conflict. Then one crash.

ResultDesk now has db.py and reports.py, and BOTH define a variable named total. Nothing breaks. Two files, same name, no fight. How?

Then a teammate moves your grades.py into a tools folder, and suddenly import grades dies: ModuleNotFoundError, though the file plainly exists.

Both mysteries have the same root: Python keeps maps of names, and lists of places to look. Learn the maps (namespaces) and the list (the search path) and both mysteries dissolve.

Theory

Same name, different registers

Three students named Riya study in three classes. No confusion ever: each class register is its own little world, and "Riya" means someone specific per register.

A namespace is a register: a mapping from names to actual objects. Every function keeps one (local), every module keeps one (global), and Python itself keeps one (built-in, where print and len live). Identical names in different registers never collide.

Theory

Scope and the LEGB lookup

Scope is the question: when code says `total`, which register does Python check?

The lookup order is LEGB, first hit wins:

  • Local: names made inside the current function
  • Enclosing: the outer function, if nested
  • Global: the module's own names
  • Built-in: print, len, sum...

One sharp edge: assigning inside a function creates a LOCAL name. To rebind a module-level name from inside a function you must declare global total first.

Practical

LEGB in twelve lines

total = 100            # G: module (global) namespace

def report():
    total = 5          # L: a NEW local name, global untouched
    print(total)       # 5   (Local wins the lookup)

report()
print(total)           # 100 (the global was never changed)

def reset():
    global total       # opt in to rebinding the global
    total = 0

reset()
print(total)           # 0

# Built-in namespace is the LAST stop:
# len, print, sum live there... until you shadow them:
# sum = 0        <- now sum() crashes: 'int' is not callable

This example runs in Gri-Learn on the web, where you can edit it and see the output.

Theory

Packages and PYTHONPATH

A package is a folder of modules, marked by an __init__.py file:

resultdesk/

├── __init__.py

├── db.py

└── reports.py

Import with dots mirroring folders: from resultdesk import db.

And where does Python hunt for modules and packages? Only the directories in sys.path: the current folder, standard locations, plus anything you add via the PYTHONPATH environment variable (export PYTHONPATH=/home/riya/tools). The teammate's crash: the tools folder was not on that list.

Quiz

x = 10 at module level. A function does x = 99 (no global statement) and the module prints x afterwards. What prints, and why?

  1. 10: the assignment created a separate LOCAL x; the global was untouched
  2. 99: functions always modify the surrounding variable
  3. Error: x is defined twice
  4. 0: Python resets shadowed variables
Show the answer

10: the assignment created a separate LOCAL x; the global was untouched

Assignment inside a function births a local name in the function's own namespace; the module-level x never hears about it. Changing the global requires the explicit global x declaration. Option B describes languages Python refuses to be; two namespaces holding the same name is normal, not an error. This exact trace, with these exact two numbers, is an exam regular.

Think first

Fix the teammate's import

grades.py now lives in /home/riya/tools, and your script (running from elsewhere) needs import grades. Before tapping: name TWO different ways to make the import succeed.

Show the answer

1. Set PYTHONPATH: export PYTHONPATH=/home/riya/tools before running: the folder joins sys.path for every Python run in that shell.

2. Append in code: import sys; sys.path.append('/home/riya/tools') before the import: a per-script fix.

(A third, cleanest for real projects: make tools a proper installed package.) The principle either way: Python searches ONLY sys.path; imports fail by absence from the list, not by files not existing.

Watch out

Shadowing: the silent namespace crime

sum = 0 at the top of a script quietly buries the built-in sum(): fifty lines later sum(scores) explodes with 'int' object is not callable and no hint why.

LEGB explains it: your Global sum now wins the lookup before Built-in is ever reached. Same disease as last lesson's csv.py shadowing the csv module: one namespace level hiding another. Treat built-in names (sum, list, max, id) as reserved.

Theory

Why this matters for the units ahead

Every import you will write (sqlite3 next lesson, pandas in Unit 4) succeeds or fails by sys.path, and every NameError you will debug is LEGB asking which register you REALLY put that name in. Two mental tools, both invisible until the day they save you an hour.

Summary

Key takeaways

  • A namespace maps names to objects; local, global and built-in namespaces coexist peacefully.
  • Lookup order is LEGB: Local, Enclosing, Global, Built-in; first hit wins.
  • Assignment in a function creates a local name; rebinding a global needs the global keyword.
  • A package = a folder of modules with __init__.py; import dots mirror folders.
  • Python searches only sys.path; PYTHONPATH adds directories to it.
  • Never shadow built-ins (sum, list, max) or module names.
  • Memory hook: same name, different class registers.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Python interaction with SQLite

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

Setting PYTHONPATH, concepts of namespace and scope; concepts of packages in Python · Database Handling using Python · Gri-Learn