What does Python's -I isolated mode do that -E and -s do not?
answer
- Each flag removes one contributor to startup
- One of them is a bundle of three
- Environment, user site directory, prepended entry
- The site module still runs under it
- -I implies -E, -s and -P, never -S
basics
~20 s-I is isolated mode. It implies -E (ignore PYTHON* environment variables) and -s (skip the per-user site directory), and on top of that it implies -P, so no script or working directory is prepended to sys.path.
solid answer
~40 sThe flags divide cleanly. `-E` makes the interpreter ignore `PYTHON*` environment variables such as `PYTHONPATH` and `PYTHONHOME`. `-s` drops the per-user site directory, the same as `PYTHONNOUSERSITE=1`. `-P` suppresses the one path entry the interpreter prepends for you - the script's directory, or the working directory. `-I` is the bundle of all three, and `sys.flags.isolated` reports it while `ignore_environment`, `no_user_site` and `safe_path` each report their own piece. What `-I` deliberately does not imply is `-S`: the `site` module still runs, so the interpreter's own site-packages, and the environment it was launched from, still work. Isolated means "nothing the invoking user contributed", not "no installed packages at all".
code
console · 1 linepython -I -c 'import sys; print(sys.flags.isolated, sys.flags.ignore_environment, sys.flags.no_user_site, sys.flags.no_site)'go deeper
Know that -I exists and means isolated: the interpreter ignores PYTHON* variables and skips the per-user install directory. Knowing the name of the flag and roughly what it protects you from is enough here.
Be able to split the bundle: -E for environment variables, -s for the user site directory, -P for the prepended path entry, -I for all three, and -S as the separate, blunter thing. Name the matching sys.flags fields.
Explain why -I stops short of -S - an isolated tool still needs its own dependencies - and demonstrate reading sys.flags off a misbehaving process instead of guessing how someone's launcher started it.
Frame the decision as blast radius: which contributors to startup a shipped tool refuses to accept from the machine it runs on, and what the team gives up in debuggability and in the ability to patch a running install from outside.
### Five switches, one axis each Python's isolation flags look overlapping until you notice that each one removes a different contributor to the interpreter's startup state. **`-E`** - ignore the `PYTHON*` environment variables. `PYTHONPATH`, `PYTHONHOME`, `PYTHONSTARTUP`, `PYTHONWARNINGS`, `PYTHONNOUSERSITE`, `PYTHONSAFEPATH` and the rest are read as if unset. `sys.flags.ignore_environment` becomes `1`. Note the direction of the trap: because `-E` discards `PYTHON*` variables wholesale, it also discards the ones you were using to harden the process. Command-line options are never affected by `-E`, which is why the flags outrank the variables when both are available. **`-s`** - do not add the per-user site directory to `sys.path`. `PYTHONNOUSERSITE=1` is the environment equivalent, `sys.flags.no_user_site` reports it, and `site.ENABLE_USER_SITE` becomes `False`. This is the switch that stops a package a user installed for themselves from being visible to your process. It does not touch the interpreter's own site-packages. **`-S`** - do not import the `site` module at startup at all. This is the blunt one: without it running, the site-packages machinery does not happen, so third-party installs generally are not importable. `sys.flags.no_site` reports it, and there is no environment variable for it. **`-P`** - do not prepend a potentially unsafe path entry. For `python app.py` that entry is the script's directory; for `python -m pkg.mod` it is the working directory; for `python -c` and the interactive prompt it is an empty string meaning the working directory. `PYTHONSAFEPATH=1` is the environment equivalent and `sys.flags.safe_path` reports it. **`-I`** - isolated mode, which implies `-E`, `-s` and `-P` together. `sys.flags.isolated` is `1`, and so are the three flags for the implied options. It is the single switch you reach for when the answer to "could anything the invoking user set change which code runs?" must be no. ### What -I deliberately leaves alone The interview point that separates a confident answer from a vague one is that **`-I` does not imply `-S`**. Under `-I` the `site` module still runs, so the interpreter's own site-packages directory is still on `sys.path` and the packages installed into that interpreter still import normally. That is the whole design: an isolated tool is meant to see its own dependencies and nothing the user contributed. Had `-I` implied `-S`, no installed tool could use `-I` and still import anything it depends on. The same reasoning explains a second thing `-I` leaves working. A virtual environment is not selected by an environment variable; the interpreter discovers it from the configuration file sitting next to the executable that was launched. So running that environment's interpreter with `-E` or `-I` does not fall back to the system installation - the environment is still in effect, because it was never a `PYTHON*` variable in the first place. `VIRTUAL_ENV` in your shell is a convenience for the prompt and the activation script, not the mechanism. ### Reading the state back Every one of these is observable, which matters when you are debugging someone else's launcher rather than writing your own. `sys.flags` is a named tuple carrying `isolated`, `ignore_environment`, `no_user_site`, `no_site` and `safe_path` among others, so a one-line probe tells you exactly how a process was started: ```python import sys print('isolated ', sys.flags.isolated) print('no env ', sys.flags.ignore_environment) print('no user ', sys.flags.no_user_site) print('no site ', sys.flags.no_site) print('safe path ', sys.flags.safe_path) ``` Running that under `-I` prints `1 1 1 0 1`: three implied options on, `-S` off, safe path on. ### Choosing between them For a tool you ship, `-I` is the default answer, because it removes the three contributors a user can change without knowing they changed anything. `-E` alone suits a build or test step that must be reproducible across developer shells but still wants the working directory importable. `-s` alone is the surgical fix for the one real failure mode that a per-user install has caused: a package installed for the user shadowing the version the tool was built against. `-S` is not an isolation flag so much as a startup-cost and debugging flag; reaching for it because it sounds like the strongest option is how people end up with an interpreter that cannot import anything they installed. One last operational note: flags are per process. A child launched with `subprocess` inherits the environment, not the parent's command line, so isolation has to be passed on explicitly if the child must have it too.
- Why would running a tool with -S instead of -I usually be a mistake?Because `-S` skips importing the `site` module, so the interpreter's own site-packages handling never happens and the tool's installed dependencies are generally not importable. `-I` is the isolation flag: it removes the environment variables, the per-user site directory and the prepended path entry, while leaving the interpreter's own installed packages exactly where they were. `-S` is about startup cost and debugging, not about isolation.
- Does -E disable the virtual environment the interpreter is running from?No. A virtual environment is discovered from a configuration file next to the executable that was launched, not from an environment variable, so ignoring `PYTHON*` variables does not undo it. `VIRTUAL_ENV` in the shell exists for the prompt and the activation script. If you run the environment's own interpreter with `-E` or `-I`, `sys.prefix` still points at the environment.
- Which flag do you reach for when a user's own installed copy of a library shadows the one your tool expects?`-s`, or `PYTHONNOUSERSITE=1`, which keeps the per-user site directory off `sys.path` while leaving everything else alone. `site.ENABLE_USER_SITE` reads `False` once it is in effect. If you also want to be sure no `PYTHONPATH` and no working directory can contribute, escalate to `-I`, which implies `-s` along with `-E` and `-P`.
saying these in an interview costs you the question
- Says -I implies -S and blocks all site-packages
- Thinks -s removes the interpreter's own site-packages
- Claims -E turns off an active virtual environment
- Believes PYTHONNOUSERSITE still works under -E
- Assumes command-line flags are inherited by subprocesses
- Treats -S as the strongest isolation option