Errors, files and virtualenvs

Reading tracebacks, using context managers safely, handling JSON, and keeping dependencies isolated.

Reading a traceback

Tracebacks print oldest call first — scroll to the bottom for the actual exception. The last few frames are almost always your own code, even when the error surfaces inside a library.

Traceback (most recent call last):
  File 'app.py', line 12, in <module>
    main()
  File 'app.py', line 8, in main
    print(items[5])
          ~~~~~^^^
IndexError: list index out of range

Handling exceptions

try:
    value = int(text)
except ValueError as e:
    print('not a number:', e)
else:
    print('parsed fine', value)      # runs if no exception
finally:
    cleanup()                        # always runs

try:
    risky()
except (OSError, ValueError):      # tuple of types
    pass                             # swallow deliberately, never silently
⚠️
Bare except: also catches KeyboardInterrupt and SystemExit, making programs hard to stop. Catch the narrowest type you can, and log something.

Use raise ... from err when re-raising, to preserve the original cause in the traceback chain.

Files with context managers

with open('data.json', encoding='utf-8') as f:
    data = json.load(f)          # file closed even on error

with open('out.txt', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2, ensure_ascii=False)

for line in pathlib.Path('app.log').read_text(encoding='utf-8').splitlines():
    if 'ERROR' in line:
        print(line)
  • json.load(f) reads from a file object; json.loads(s) parses a string.
  • ensure_ascii=False keeps non-Latin characters readable instead of escaping them.
  • Use pathlib for path building — Path('a') / 'b' works across platforms.

Environments and packages

python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate

pip install requests
pip freeze > requirements.txt
pip install -r requirements.txt
💡
Add .venv/ to .gitignore. Committing an environment breaks every teammate on a different OS.

FAQ

Should I catch all exceptions?
At a top-level boundary (CLI entry point, request handler) yes, to log and return a friendly error. Deep inside code, no — let it propagate to something that can decide.
Why use 'with' instead of close()?
The context manager guarantees closing even if the body raises — no leaked file handles under load.

JSON basics Python: getting started

Last refreshed 2026-09-17.