[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