Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PEP 690: Lazy Imports #2569

Merged
merged 18 commits into from
May 3, 2022
Merged

PEP 690: Lazy Imports #2569

merged 18 commits into from
May 3, 2022

Conversation

Kronuz
Copy link
Contributor

@Kronuz Kronuz commented May 2, 2022

This is the PEP proposal for Lazy Imports in Python

@Kronuz Kronuz requested a review from a team as a code owner May 2, 2022 22:05
pep-9999.rst Outdated Show resolved Hide resolved
Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just found one typo

pep-9999.rst Outdated Show resolved Hide resolved
@carljm
Copy link
Member

carljm commented May 2, 2022

cc @warsaw

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Copy link
Member

@AA-Turner AA-Turner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick review as these comments will be lost when you change the filename.

A

pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
@AA-Turner AA-Turner requested a review from warsaw May 2, 2022 22:18
Kronuz and others added 4 commits May 2, 2022 15:18
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
@warsaw
Copy link
Member

warsaw commented May 2, 2022

Doc builds are still failing.

pep-9999.rst Outdated Show resolved Hide resolved
Co-authored-by: Carl Meyer <carl@oddbird.net>
.github/CODEOWNERS Outdated Show resolved Hide resolved
Co-authored-by: Carl Meyer <carl@oddbird.net>
@AA-Turner AA-Turner added the new-pep A new draft PEP submitted for initial review label May 2, 2022
@AA-Turner AA-Turner changed the title PEP 9999: Lazy Imports PEP 690: Lazy Imports May 2, 2022
pep-0690.rst Outdated Show resolved Hide resolved
Co-authored-by: Carl Meyer <carl@oddbird.net>
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated Show resolved Hide resolved
pep-9999.rst Outdated
.. code-block py
from importlib import set_eager_imports

set_eager_imports(["one.mod", "another"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a context manager in importlib so that you could do something like:

with importlib.eager():
    # all things inside this with block will be opted out of lazy imports

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea. @Kronuz was concerned that there might be confusion about whether the effect of with importlib.eager(): is shallow or deep. I.e. does it make all imports eager that occur recursively "within" that block, or just the imports directly in this module? I prefer shallow, because it's less action-at-a-distance; I'd rather know when reading a module whether the imports in it will be shallow or lazy (presuming lazy imports is enabled at all.) I think if we don't suggest the possibility of "deep" effect then the shallow version should be fairly intuitive...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the effect is shallow, the context manager can literally be a no-op, since as discussed elsewhere in the PEP, context managers automatically make imports within them eager, for exception-handling reasons.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it would enable deep eager imports because it's hard otherwise to enforce that, but it could be controlled by a flag, e.g.:

with importlib.eager(deep=False)
    ...
with importlib.eager(deep=True)
    ...

Or shallow as the flag name instead of deep. Either way, maybe shallow eagerness should be the default?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the effect is shallow, the context manager can literally be a no-op, since as discussed elsewhere in the PEP, context managers automatically make imports within them eager, for exception-handling reasons.

Oh yeah, right!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the importlib.set_eager_imports() API currently proposed in the PEP serves the same use case as with importlib.eager(deep=True) does. But I think set_eager_imports() is a more predictable and less error-prone (though arguably less aesthetic) way to do it, since it ensures that certain selected modules will always use only eager imports, regardless of where they are imported from, whereas if you use the deep context manager, you never know whether some other module might first import the same thing without the deep-eager context, so you might be confused why that thing still gets imported with laziness initially..

So my inclination would be to provide importlib.set_eager_imports() but not provide a deep context manager.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see that. The one thing that maybe bothers me is that set_eager_imports() doesn't say to me either deep or shallow imports, and it implies shallow imports because you have to explicitly name some module paths. The other question is whether it's possible to unset eager imports you've specified in this call (or whether you even need to). With the context manager at least, you understand the limited effective scope of the eagerness.

It's totally fine to be opinionated in the PEP and I support either interpretation. (It will likely get bikeshedded anyway 😄 .) The PEP should include a discussion of the options though, perhaps in the rejected ideas section.

pep-9999.rst Outdated
foo.Bar()

In this case, with lazy imports enabled, the import of ``foo`` will not
actually occur while the addition to ``sys.path`` is present.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably important to discuss, as we chatted about, whether it makes sense to separate finder from loader execution. IOW, I believe this PEP is proposing that neither finder nor loader executes when the import statement is lazy. It could run the finder and cache those results, but defer loader execution until eager time. I'm not saying it should, but the PEP should be explicit about this and perhaps discuss it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is currently discussed below under rejected ideas.

pep-9999.rst Outdated
import side effects is the registry pattern, where population of some
external registry happens implicitly during the importing of modules, often
via decorators. Instead, the registry should be built via an explicit call
that perhaps does a discovery process to find decorated functions or classes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this break the click use case? The PEP should at least discuss this topic, as CLIs are the primary motivator and click is a very common CLI library.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if click subcommands are created in multiple modules, those modules need to be forced to eager import in order to get the click subcommands registered. Will note this specifically.

pep-9999.rst Outdated

* Don't use inline imports, unless absolutely necessary. Import cycles should
no longer be a problem with lazy imports enabled, so there’s no need to add
complexity or more opcodes in a potentially hot path.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any effects on namespace packages?

pep-9999.rst Outdated Show resolved Hide resolved
@AA-Turner
Copy link
Member

You need to resort your CODEOWNERS entry.

A

@AA-Turner
Copy link
Member

Also, you probably need to add yourself to AUTHOR_OVERRIDES (there's no way of detecting spanish style surnames, so currently you appear in the index as "Bravo")

image

A

Copy link
Member

@AA-Turner AA-Turner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of your code blocks are rendering, the proposed fixes them.

You can use https://pep-previews--2569.org.readthedocs.build/pep-0690/ as a live preview.

A

pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
pep-0690.rst Outdated Show resolved Hide resolved
@AA-Turner
Copy link
Member

@CAM-Gerlach I marked your code-block suggestions as resolved as the :: should be on the .. code-block line, not the previous para, and the explicit syntax is prefered if possible.

A

@CAM-Gerlach
Copy link
Member

I prefer it as well, I just didn't want to overcomplicate things for authors and lead to a greater chance of a syntax error as we saw here, yours didn't show up for me inline on the Files pane while I was reviewing.

Copy link
Member

@AA-Turner AA-Turner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending addressing all of Barry's points.

A

Copy link
Member

@CAM-Gerlach CAM-Gerlach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks; LGTM from a rendering/syntax perspective. If you'd like me to do a copyediting pass, either as suggestions here or a separate PR once this is merged, let me know.

@warsaw
Copy link
Member

warsaw commented May 3, 2022

Just a quick note about the things we chatted about. Update the PEP to discuss:

  • implication for namespace packages (they should just work)
  • implications for click (probably need to eager import your subcommands, but knock on imports get lazied)
  • documenting that python3 -v and -X importtimes should both just work

@carljm
Copy link
Member

carljm commented May 3, 2022

@warsaw I think the latest version addresses all your comments!

@CAM-Gerlach Might be easier at this point to get it merged, if it looks good enough - a copy-editing pass as separate PR after land would be very welcome!

@AA-Turner AA-Turner requested a review from warsaw May 3, 2022 18:14
pep-0690.rst Outdated Show resolved Hide resolved
@AA-Turner
Copy link
Member

Might be easier at this point to get it merged

It also means that @Kronuz would no longer be considered a "new contributor", and we wouldn't keep having to click the button to run CI!

A

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
@warsaw
Copy link
Member

warsaw commented May 3, 2022

Might be easier at this point to get it merged, if it looks good enough - a copy-editing pass as separate PR after land would be very welcome!

Agreed!

Copy link
Member

@warsaw warsaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job on this PEP! Any changes that are needed after this should be done as separate PRs.

@warsaw
Copy link
Member

warsaw commented May 3, 2022

@CAM-Gerlach I'll leave the final merge to you.

Copy link
Member

@CAM-Gerlach CAM-Gerlach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! Make sure to post the PEP's discussion thread in the Discourse PEPs category (per @warsaw 's recommendation), link the thread in the Discussions-To header and the Post-History (I can help get that started if you like), and an announcement linking to the PEP and thread on Python-Dev. Thanks!

@CAM-Gerlach CAM-Gerlach merged commit 376341a into python:main May 3, 2022
@CAM-Gerlach
Copy link
Member

Hey @ewdurbin , when I merged this, the site was rebuilt and redeployed and the new PEP is visible in PEP 0, but when I actually visit the PEP page (as linked there), I get a GitHub Pages 404, even if I force (shift) reload clearing cache, as of the time this comment was posted. I'm guessing maybe Fastly caching is caching the 404 page? What's the timeout, and is there any way to avoid that, since it means for some time after new PEPs are published, the links are visible and indexable, but the PEPs themselves are not, which is not ideal.

image

Or is something else going on?

@hugovk
Copy link
Member

hugovk commented May 3, 2022

https://peps.python.org/pep-0690/ is loading fine for me.

@CAM-Gerlach
Copy link
Member

I tested in a private window, @JelleZijlstra tested on his computer and @FFY00 tested on his phone, all on the PyCon conference WiFi, and it all resolves to a 404, but when I tested on my phone on LTE, it works. So it seems its some kind of caching layer specific to the conference internet (and not a regional/PoP thing on the Fastly/GHP side). I also loaded it myself just before it actually deployed, which probably triggered the caching; if I'd waited 60 seconds, it likely wouldn't have cached it.

So the page is live for everyone but us at PyCon, thanks to my cache poisoning 😆

@ewdurbin
Copy link
Member

ewdurbin commented May 4, 2022

Obviously late to the party, but I would love to see the headers from the responses to determine if it was indeed a caching proxy run by the convention center or a Fastly POP thing.

@hugovk
Copy link
Member

hugovk commented May 4, 2022

I guess the interesting headers are now gone for that page, but we can repro by looking at any other 404 page?

For example, there's Fastly cache headers on https://peps.python.org/pep-9991/

@ewdurbin
Copy link
Member

ewdurbin commented May 4, 2022

I want to see the headers on the responses inside the convention center specifically.

@JelleZijlstra
Copy link
Member

Unfortunately I don't think any of us saved the headers. Maybe we'll see it again with another PEP at next year's PyCon :)

@hugovk
Copy link
Member

hugovk commented May 4, 2022

Unless someone wants to volunteer to attend the 2022 Climbing Wall Association Summit or 2022 Society of Gastroenterology Nurses and Associates Annual Course? :)

https://conventioncalendar.com/saltlakecity

@CAM-Gerlach
Copy link
Member

Obviously late to the party, but I would love to see the headers from the responses to determine if it was indeed a caching proxy run by the convention center or a Fastly POP thing.

Since it worked on our phones at the same time and location, would Fastly expose a different POP to mobile network operators vs. the conference's ISP? If not, then it would seem to be a caching layer between the ISP and the local WiFi router, but if so, we should be able to reproduce it next time we add a PEP...

Unfortunately I don't think any of us saved the headers. Maybe we'll see it again with another PEP at next year's PyCon :)

The critical aspect, I think, was me poisoning the cache just before the PEP went live 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new-pep A new draft PEP submitted for initial review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants