Live data from Hacker News

PEP 810 – Explicit lazy imports

peps.python.org

101–110 of 247 posts

Re: PEP 810 – Explicit lazy imports

#101
post #75
post #67

I don't hate it but I don't love it. It sounds like everyone will start writing `lazy` before essentially every single import, with rare exceptions where eager importing is actually needed. That makes Python code visually noisier. And with no plan to ever change the default, the noise will stay forever. I would have preferred a system where modules opt in to being lazy-loaded, with no extra syntax on the import side.…

I don't think this makes sense to be on the module side, the caller is the one with the information as to whether the module can or needs to be lazily loaded. There's nothing really for the module being imported to decide, every module can be lazily loaded. Even if it has side effects the caller may want to defer those as well.

> Even if it has side effects the caller may want to defer those as well.

But that's rare, and could be handled with existing workarounds.

Normally, a module needs to be eagerly imported if and only if it has side effects.

Re: PEP 810 – Explicit lazy imports

#102
post #19
post #8

Wake me up when we can import a module by relative file path.

You… can? I mean in the strictest sense you're technically not importing by file path but if you make your folder a module by slapping an __init__.py in there then your relative imports will follow the directory tree. I think as of Python 3.3 the init file is optional so it will do it by default but I can't remember if there are still some cases where it's required. The only thing you can't do is go "up" to a higher…

> if you make your folder a module by slapping an __init__.py in there then your relative imports will follow the directory tree

haha no

> all of the importlib machinery is at your disposal

This breaks all tooling. Awful option.

Re: PEP 810 – Explicit lazy imports

#103
post #60

Earlier quoted context omitted.

It's been explained many times before why this is not possible: the library doesn't actually have a version number. The distribution of source code on PyPI has a version number, but the name of this is not connected to the name of any module or package you import in the source code. The distribution can validly define zero or more modules (packages are a subset of modules, represented using the same type in the Pytho…

> It's been explained many times before why this is not possible: the library doesn't actually have a version number. The distribution of source code on PyPI has a version number, but the name of this is not connected to the name of any module or package you import in the source code. You're making the common mistake of conflating how things currently work with how things could work if the responsible group agrees to…

No, changing this breaks the world. A huge fraction of PyPI becomes completely invalid overnight, and the rest fails the expected version checks. Not to mention that the language is fundamentally designed around the expectation that modules are singleton. I've written about this at length before but I can't easily find it right now (I have way too many bookmarks and not nearly enough idea how to organize them).

Yes, you absolutely can create a language that has syntax otherwise identical to Python (or at least damn close) which implements a feature like this. No, you cannot just replace Python with it. If the Python ecosystem just accepted that clearly better things were clearly better, and started using them promptly, we wouldn't have https://pypi.org/project/six/ making it onto https://pypistats.org/top (see also https://sethmlarson.dev/winning-a-bet-about-six-the-python-2...).

Re: PEP 810 – Explicit lazy imports

#104
post #67

I don't hate it but I don't love it. It sounds like everyone will start writing `lazy` before essentially every single import, with rare exceptions where eager importing is actually needed. That makes Python code visually noisier. And with no plan to ever change the default, the noise will stay forever. I would have preferred a system where modules opt in to being lazy-loaded, with no extra syntax on the import side.…

We heard that about types, the walrus, asyncio, dataclasses and so much more. But it didn't happen, if people don't need something (and many don't know it exists or what it does), it's unlikely they use it. In fact, half of the community basically uses only a modernized set of python 2.4 features and that's one of the beauties of the language. You don't need a lot to be productive, and if you want more, you can optio…

Perhaps people won't use it. But I for one want it to be used, and I will certainly be using it in my own code if the PEP is accepted. Startup time is very important to me, more important than the cost of making the code noisier. I just wish I didn't have to make that tradeoff in the first place.

Re: PEP 810 – Explicit lazy imports

#105
I don’t really agree with the premise:

> The dominant convention in Python code is to place all imports at the beginning of the file. This avoids repetition, makes import dependencies clear and minimizes runtime overhead.

> A somewhat common way to delay imports is to move the imports into functions, but this practice requires more work [and] obfuscates the full set of dependencies for a module.

The first part is just saying the traditions exist because the traditions have always existed. Traditions are allowed to change!

The second part is basically saying if you do your own logic-based lazy imports (inline imports in functions) then you’re going against the traditions. Again, traditions are allowed to change!

The point about the import graph being obfuscated would ring more true if Python didn’t already provide lightning fast static analysis tools like ast. If you care about import graphs at the module level then you’re probably already automating everything with ast anyway, at which point you just walk the whole tree looking for imports rather than the top level.

So, really, the whole argument for a new lazy keyword (instead of inlining giant imports where they are needed) is because people like to see import pytorch at the top of the file, and baulk at seeing it — and will refuse to even look for it! — anywhere else? Hmmm.

What does seem like a pain in the ass is having to do this kind of repetitive crap (which they mention in their intro):

  def f1():
    import pytorch
    …

  def f2():
    import pytorch
    …

  def f3():
    import pytorch
    …
But perhaps the solution is a pattern where you put all your stuff like that in your own module and it’s that module which is lazy loaded instead?

Re: PEP 810 – Explicit lazy imports

#106
post #32

Love this. My https://llm.datasette.io/ CLI tool supports plugins, and people were complaining about really slow start times even for commands like "llm --help" - it turned out there were popular plugins that did things like import pytorch at the base level, so the entire startup was blocked on heavy imports. I ended up adding a note to the plugin author docs suggesting lazy loading inside of functions - https://llm.…

Parse the command line and do things like "--help" without doing the imports. Only do imports when you know you need them -- or as an easy approximation, only if the easy command line options have been handled and there's still something to do.

In the llm project, plugins can modify the command line arguments, so it's not that simple.

Re: PEP 810 – Explicit lazy imports

#108

Earlier quoted context omitted.

Parse the command line and do things like "--help" without doing the imports. Only do imports when you know you need them -- or as an easy approximation, only if the easy command line options have been handled and there's still something to do.

In the llm project, plugins can modify the command line arguments, so it's not that simple.

Yea, that's the core problem here: plugins can add new CLI subcommands, which means they all need to be loaded on startup.

https://llm.datasette.io/en/stable/plugins/plugin-hooks.html...

Re: PEP 810 – Explicit lazy imports

#109

Earlier quoted context omitted.

> It's been explained many times before why this is not possible: the library doesn't actually have a version number. The distribution of source code on PyPI has a version number, but the name of this is not connected to the name of any module or package you import in the source code. You're making the common mistake of conflating how things currently work with how things could work if the responsible group agrees to…

No, changing this breaks the world. A huge fraction of PyPI becomes completely invalid overnight, and the rest fails the expected version checks. Not to mention that the language is fundamentally designed around the expectation that modules are singleton. I've written about this at length before but I can't easily find it right now (I have way too many bookmarks and not nearly enough idea how to organize them). Yes,…

The hard part is making the change. Adding an escape hatch so older code still works is easy in comparison.

Nobody is claiming this is a trivial problem to solve but its also not an impossible problem. Other languages have managed to figure out how to achieve this and still maintain backwards compatibility.

Re: PEP 810 – Explicit lazy imports

#110
post #88

Earlier quoted context omitted.

Relative imports have been supported for approximately forever ( https://stackoverflow.com/questions/72852 ). If you mean "by explicitly specifying a path string" (as opposed to a symbolic name), that has also been supported for approximately forever ( https://stackoverflow.com/questions/67631 ). Today, the `importlib` standard library exposes all the steps of the import process — including figuring out where the sou…

Nope. Relative imports work by relative package path, which is not at all the same. Often when you run Python you don't even have a package path. Using `importlib` is a horrible hack that breaks basically all tooling. You very very obviously are not supposed to do that.

> Relative imports work by relative package path, which is not at all the same.

Exactly. This gives you the flexibility to distribute a complex package across multiple locations.

> Often when you run Python you don't even have a package path.

Any time you successfully import foo.bar, you necessarily have imported foo (because bar is an attribute of that object!), and therefore bar can `from . import` its siblings.

> Using `importlib` is a horrible hack that breaks basically all tooling. You very very obviously are not supposed to do that.

It is exactly as obvious (and true) that you are not "supposed to", in the exact same sense, directly specify where on disk the source code file you want to import is. After all, this constrains the import process to use a source code file. (Similarly if you specify a .pyc directly.) Your relative path doesn't necessarily make any sense after you have packaged and distributed your code and someone else has installed it. It definitely doesn't make any sense if you pack all your modules into a zipapp.

Post reply on HN