[Python-Dev] __import__ problems

Steven D'Aprano steve at pearwood.info
Fri Nov 28 17:17:37 CET 2008


On Fri, 28 Nov 2008 11:59:39 pm Mart Somermaa wrote:
> Nick Coghlan wrote:
> > As Hrvoje has pointed out, 'sys' is part of the internal
> > interpreter machinery - it's there as soon as the interpreter
> > starts. The import call for it just grabs it out of the module
> > cache and creates a reference to it in the current namespace.
>
> I understand that, but
>
> Explicit is better than implicit.
>
>  --> non-explicit import sys and __import__(modname) to access
>
>      sys.modules[modname]

Importing sys is explicit. You actually say "import sys" -- how much 
more explicit can you get?


> Simple is better than complex.
>
>  --> three lines for a common use case instead of one

Simple doesn't mean shorter. The three line idiom is simple, because 
each line is simple and they combine in a simple way.

import sys  # does the same thing import sys always does
__import__(modname)  # does the same thing __import__ always does
modobj = sys.modules[modname]  # just a normal lookup

> Readability counts.
>
>  --> why is sys imported in this WSGI app (that shouldn't generally
>      touch any of the common sys.argv, sys.stdout etc)?!
>      (500 lines later) aha, to access sys.modules

sys is imported for the same reason that any module is imported: because 
some functionality provided by the module is needed. "I don't want to 
import a module" is not, on its own, a good enough reason to add extra 
complexity to a function.

There's no readability loss by importing a module at the top of the 
program and not using that module until some "500 lines" later. That's 
normal for modules.


> There should be one-- and preferably only one --obvious way to do it.
>
> --> should I use the 3-line idiom? should I use the getattr() idiom?

"Although that way may not be obvious at first unless you're Dutch."

I would say the three line idiom is obvious. At least, it's obvious now 
that I've learnt that there is a sys.modules.

>     Ideally, __import__() should support the only obvious way.
>
> In short, the three-line version doesn't convey the intent in an
> obvious way and does more work than is necessary.

I disagree with both those claims.

However, having disagreed with your arguments, I will say this: I think 
a "tail" argument to __import__ would be more elegant:

z = __import__('x.y.z', tail=True)  # or submodule in your initial post

I think that it is unintuitive that __import__(x.y.z) returns module x 
instead of z. When I say "get me the book inside the box inside the 
wardrobe", I expect to get the book, not the entire wardrobe! So even 
though I disagree with all your criticisms of the three-line idiom, I 
think there is an elegance to your idea that the three-line idiom 
doesn't have. I'm +0.5 on the idea of an extra argument that says, "no, 
really, just give me the book, I don't need the wardrobe".

But I think if you want to convince others, you're going to need to come 
up with more positive reasons for preferring the extra argument rather 
than rely on dubious criticisms of the three-line idiom: the 
three-liner is short, simple, obvious, readable and explicit, but your 
solution would be even shorter, more readable, and more explicit. I 
think it loses on the obvious and possibly on simple. The advantage is 
you've already done the work rather than expecting somebody else to do 
it for you.

Good luck. 



-- 
Steven


More information about the Python-Dev mailing list