Exercise 3: debug=False Genuinely Never Starts the Watch Loop — Possible Solution ==================================================================== THE TEST ------------------------------ proc = subprocess.Popen( [sys.executable, 'manage.py', 'runserver', '--port', '8954'], # deliberately NO --debug stdout=log_file, stderr=subprocess.STDOUT, ) pid_before = pid_on_port(8954) # genuinely edit the watched source file on disk with open('manage.py', 'a') as f: f.write('\n# an edit that must NOT trigger a reload\n') time.sleep(2.0) # the same real window the --debug case needed to reload pid_after = pid_on_port(8954) VERIFIED, REAL RESULT ------------------------------ initial GET: (200, b'hello') PID listening before edit (no --debug): 17012 GET after edit, still no --debug: (200, b'hello') PID listening after edit: 17012 PID stayed fixed -- confirming debug=False genuinely never watches at all: True The PID listening on the port was identical before and after the real file edit — the process never restarted, and the server kept serving the exact same response it served before the edit, confirming it never even noticed the change. WHY THIS WORKS ------------------------------ cmd_runserver()'s own if args.debug: branch is the only place run_with_reloader() (and therefore FileWatcher, and therefore the whole poll loop) is ever constructed or started. When --debug isn't passed, that whole branch is simply never reached — server.serve_forever() runs directly, with no watcher object ever created and no background polling thread ever spawned. There's no "disabled" state to check on every request the way Chapter 8's own template-reload check needed a debug guard inside the request path itself; here, gating happens once, at startup, by never building the reloader machinery at all. WHY THIS WORKS AS AN ANSWER ------------------------------ It verifies absence rather than presence — proving a real reload does NOT happen is a genuinely different (and easy to get wrong) kind of test than proving one does, since a test that simply forgets to check would silently "pass" either way. Using the identical real time window (time.sleep(2.0)) the --debug case in the main chapter actually needed to reload rules out "it just hasn't happened yet" as an explanation — the same wait, with no --debug flag, produces genuinely no change at all, confirmed by the PID staying fixed rather than inferred from the response body alone.