os: Environment and Filesystem
os: Environment and Filesystem
import os
port = int(os.getenv("PORT", "8000")) # default when unset
os.environ["MODE"] = "prod" # visible to child processes
root = Path(os.environ["HOME"]) # os.environ is a mutable mapping
for dirpath, dirnames, filenames in os.walk("src"): # top-down by default
...
os.makedirs("out/logs", exist_ok=True)
os.remove("tmp.bin") # unlink alias; raises FileNotFoundError
print(os.sep, os.path.join("a", "b"), os.name) # '/', 'a/b', 'posix'
Prefer os.getenv(key, default) over os.environ.get for readability. Spawn external tools with subprocess.run(["git", "status"], check=True) — not os.system, which routes through the shell, returns only an exit status, and invites quoting bugs.
sys: Arguments, Paths, and Streams
sys: Arguments, Paths, and Streams
import sys
if len(sys.argv) != 2: # argv[0] is the script path
print("usage: tool <file>", file=sys.stderr)
sys.exit(2) # raises SystemExit with code 2
sys.path.insert(0, "vendor") # search path is a plain list
print(sys.version_info[:2], sys.platform) # (3, 12), 'win32' / 'linux'
data = sys.stdin.read()
sys.stdout.reconfigure(encoding="utf-8") # fix mojibake on Windows consoles
sys.stdout.write("ok\n")
sys.exit never "returns" — it raises SystemExit, which finally blocks still see, so cleanup code runs normally. sys.modules and sys.path are inspectable at runtime; sys.setrecursionlimit(10000) trades headroom for stack risk — pushing far beyond available C-stack can segfault the interpreter, not raise a Python error.
Pitfalls and Interview Angles
Pitfalls and Interview Angles
Platform checks: os.name gives coarse families (posix/nt); sys.platform distinguishes linux from darwin from win32. Use sys.platform when behavior differs per OS.
Encoding. Piping UTF-8 through sys.stdout under a legacy Windows code page raises or mangles text; PYTHONIOENCODING=utf-8 or reconfigure fixes it.
Environment snapshots. Children inherit os.environ at spawn time — later edits do not retroactively change a running process.
Interview angle: design a small CLI — parse sys.argv (or argparse), return nonzero exit codes on failure, write diagnostics to stderr, and describe how you would make the same script locate its data directory portably using Path(__file__) rather than the cwd.
Quiz
1. What does sys.exit(2) actually do?
2. Why prefer subprocess.run([...]) over os.system("cmd")?
3. Where does sys.path[0] point when running python script.py?
Flashcards
Question
os.getenv vs os.environ
Click to reveal answer
Answer
getenv(key, default) reads cleanly; os.environ is a live mutable mapping synced with the process environment.
Question
sys.argv layout
Click to reveal answer
Answer
argv[0] = script path; remaining entries are user arguments (use argparse to parse).
Question
sys.exit mechanism
Click to reveal answer
Answer
Raises SystemExit; the interpreter converts it to the process exit code.
Question
os.system vs subprocess
Click to reveal answer
Answer
os.system = shell string, status only; subprocess.run(list, check=True) = safe args, captured output.
Revision Notes
Key Takeaways
- 1. os handles environment and filesystem; sys handles interpreter state and CLI plumbing
- 2. Exit codes and stderr are the contract of any real command-line tool
- 3. Avoid shell strings, set encodings explicitly, and anchor data paths to __file__
Interview Tips
- • Show you know argv[0] and exit-code conventions when asked about CLI design
- • Explain why os.system is a security and correctness problem, naming the shell-quoting failure mode
Cheat Sheet
os.getenv(k,def)/environ; os.walk/makedirs; subprocess.run([...],check=True); sys.argv[0]=script, sys.exit raises SystemExit; sys.path leads with script dir.
Continue Learning
Before You Start
- No prerequisites listed.