Thanks for all the great discussion! Consolidating replies to a few different things that have come up:
Several people (@methane, @pf_moore, @notatallshaw, @layday) have observed that neither -L
nor an env var are usable ways for a distributor of a Python application to turn this on (particularly an application distributed via Python packaging.) I agree this is a problem.
If there were a reliable cross-platform way for pip/setuptools to support creating script entry points with arbitrary Python CLI flags (as @jack1142 suggested) that would be really neat. I donât know how feasible that is.
The other way we can fix this (as @methane suggested) is to provide a programmatic API (e.g. importlib.set_lazy_imports(True)
) to globally enable lazy imports from that point forward. Thereâs no technical obstacle preventing this. What I donât love is that it allows libraries to try to assert control over this setting, which I think belongs in the hands of the application developer / integrator. But it wouldnât be Pythonâs first global config thatâs programmatically settable and that libraries probably shouldnât touch (hello there, entire import subsystem). I think we should add this API to the PEP.
Re suggestions from @brandtbucher and @itamaro about clearing the lazy lookup function from module dicts: this seems worth experiments once we have an implementation ported to 3.12. Iâve added it to the implementation todo list.
Re testing to see if your codebase remains import-cycle-free, if your main test suite runs with lazy imports enabled:
I donât think thereâs any need for eager_imports
here; it would just look like one or a few smoke tests of your library, run without -L
.
I agree with @brettcannon that while a library certainly could add -L
as a full new axis to its test matrix, doubling the size of the matrix, in practice it will probably be fine to just run tests with -L
(if you care to support it) and have just one or a few smoke tests verifying your library imports without -L
.
There is an important question here also about what PEP 690 would mean for the CPython buildbots. I think since the effect of lazy imports is very much not platform-tied, one buildbot running the test suite under lazy imports should suffice.
This would be lovely, but Iâm not sure how it could work. You canât import both eagerly and lazily, and if youâre importing lazily it doesnât seem possible to me to reliably detect that eager imports would have caused a cycle. I can imagine some best-effort approaches, but an imprecise approach seems worse in practice than just trying to run the code under eager imports.
I think you still might be overstating the real impact. In a library like pydantic or FastAPI, there may be some side effects of importing a module that defines some model classes, but you very likely also use those model classes directly in your code. As long as thatâs true, they will be imported (maybe just a bit later than they would have been otherwise) and everything will likely work fine. Import side effects are not necessarily a problem for lazy imports; the real problem is modules that are imported only for their side effects, and nothing from them is otherwise used. This is not as common, since it also causes problems with e.g. linters complaining about unused imports. (The change in timing of the import can also be a problem in some cases, but not usually.)
In any case, if you play with it weâll welcome your reports of what breaks and how hard it was to track down! Thatâs valuable data. Or experience so far (using this with a number of large CLIs with lots of dependencies) is that breakage, when it occurs, is not hard to to fix with a very limited set of module opt-outs that still preserves almost all the benefit.
(Iâll admit that Iâve had to track down enough ugly problems caused by the inherently unpredictable ordering of import side effects, even sans lazy imports, that I wonât be sad if one effect of PEP 690 is to apply some additional design pressure over time discouraging Python libraries from relying on them.)