Changing a Python package for one workflow can break another. Copying every dependency into every project has its own preparation and storage cost. I chose project virtual environments that can read common installations while retaining additions and overrides locally.
Check the actual interpreter rather than the environment label
ProjectPython identifies a Python executable beneath the project and creates a virtual environment when it is missing. System-site-packages enables reading common dependencies while keeping a separate project installation location.
Even an existing executable is checked by actually printing sys.prefix and comparing it with the expected project root. A file named Python does not establish the right environment. A mismatch stops preparation explicitly. Configuration text and the interpreter actually running need separate evidence.
Shared reading is not complete dependency independence
Because common packages remain readable, changes to the base environment can affect a project. This is not a claim of fully pinned dependencies or reproducible deployment. Project-local additions and an entirely locked dependency graph solve different problems.
A workflow needing long-term exact versions may require lock files, installation records and reconstruction in a clean environment. This capability reduces unintended shared writes between projects. Creating a virtual environment cannot remove all deployment and compatibility responsibilities.
Use the project environment for scripts and notebooks
Each project runtime creates its ProjectPython and supplies its ensure function to the runner and notebook service. That avoids displaying project A while its kernel silently uses a default interpreter. Different execution surfaces resolve project packages through the same intended environment.
Sharing that environment does not mean sharing a process or variables. Dependency lookup and kernel memory have different lifetimes. Environment selection and execution state therefore need separate descriptions and checks rather than one success standing in for both.
Handle duplicate preparation and failure explicitly
Ensure reuses a pending promise so one instance does not prepare the same environment concurrently. Failure clears that promise, permitting a later deliberate preparation. Creation and interpreter checks also have time and output bounds rather than waiting indefinitely.
This does not provide a package-installation lock across every external process. Another process modifying the same folder requires separate coordination. Local preparation deduplication and operating-system-wide write control are different guarantees. Stating the smaller scope helps an integrator identify missing protections.
Test the actual installation locations
The existing isolation test writes a synthetic module into A's local site-packages and checks that B cannot find it. It also compares actual prefixes and notebook paths. Package-location separation and equal-name variable separation have different assertions.
I read the test and current environment wiring without installing packages into operational projects. Isolation of one synthetic module does not establish compatibility of every dependency combination. Native libraries and GPU dependencies require their own actual environment checks rather than being inferred from this test.
Reduce the scope of a company-specific change
Different companies' workflows need different packages and material. Installation and execution ownership prevent one improvement from casually changing another customer's environment. Shared readable assets and localized modifications provide a useful maintenance boundary.
I treat a virtual environment as that boundary, not a security sandbox. Python still runs with actual local user permissions. Dependency separation, permission isolation and reproducible deployment need independent checks. Together those distinctions make the consequences of later changes explainable.