Personal tools
You are here: Home Weblog Archive 2008 December 03 Specific imports versus module imports in Python
Document Actions
  • Send this page to somebody
  • Print this page
  • Add Bookmarklet

Specific imports versus module imports in Python

by tibi last modified 2008-12-03 13:53
Filed Under:

I've always been a fan of explicit, separate imports in Python, vs generic module imports. Maybe it's because I like things to be explicit, or I've been spoiled by the way Eclipse Pydev deals with auto-importing, but I have an aversion towards generic module imports. To keep the code style consistent, I even rewrite to this style any foreign code that ends up in my code.

Specifically, I'm talking about:

from foo import Bar
Bar()

vs

import foo
foo.Bar()

Needless to say, I like the first style better.

There are advantages and disadvantages for each of the above methods:

  • general module imports demand less from the editor (the programmer needs to type less "import" lines and the editor doesn't need to be very much aware of Python - emacs and vim users will probably favor this style)
  • but it makes it hard sometimes to figure out where a module comes from. Example: you're deep down reading a module and you encounter a line referencing the component module. Now, where does that component module comes from? Could be both of the following imports:
from zope.app import component
from zope import component

Of course, some people sensed this problem and write code like:

class MyView(object):
    template = zope.app.pagetemplate.ViewPageTemplateFile('template.pt')

But this code is hard to read, hard to write and is almost at the limit with the self-imposed line length of 80 characters, which means most of the times it needs to be broken in two lines.

Today I became aware of what I consider the biggest advantage of using specific import (from foo import Bar). Heavy refactoring, in the absence of a comprehensive test suite, is a lot easier! When starting the program, the imports will fail and you get an immediate pointer to where you need to make a fix. If I would have used a generic module import, the error will have appeared only when trying to use the piece of code that calls foo.Bar().

TL;DR: use specific imports! If your editor doesn't support it, take some time to look at Eclipse Pydev or Netbeans, two free IDEs with Python support. You'll get:

  • easier refactoring
  • better code legibility
  • I'll be happier when I need to reuse code snippets :-)

what about performance

Posted by Anonymous User at 2008-12-03 13:54
Once debugged, the most important question for me which you didn't answer is: does a specific vs. module import make any difference in the run-time performance?

Interesting question

Posted by tibi at 2008-12-03 14:27
Of course, I'd rather have code legibility (that's one of the reasons we're using Python, right?).

I didn't do such a benchmark, although I have thought about it. I think there are two aspects to watch for: memory consumption and speed. My intuition says that memory usage would be the same, while the speed would be just a tiny bit faster in favor of specific imports

The logic is not very strong in this one

Posted by Anonymous User at 2008-12-03 15:06
"There are advantages and disadvantages for each of the above methods:

* general module imports demand less from the editor (the programmer needs to type less "import" lines and the editor doesn't need to be very much aware of Python - emacs and vim users will probably favor this style)
* but it makes it hard sometimes to figure out where a module comes from. Example: you're deep down reading a module and you encounter a line referencing the component module. Now, where does that component module comes from? Could be both of the following imports"

So you show an advantage of general imports, and a disadvantage of specific ones, and then ask me to pick specific imports, which have no demonstrated advantages and two demonstrated problems. Why? This post is nonsense.

You're right, my example is broken

Posted by tibi at 2008-12-03 15:10
I do consider the example I've given to be a "general" module import because "component" is a module and I didn't import functions and classes from it, so the two points above refer to the general import.

The specific import example, using the component module would be:

>>> from zope.component import getUtility

insted of

>>> from zope import component
>>> component.getUtility(...)

But now you're just shifting the problem

Posted by Anonymous User at 2008-12-03 17:48
You still don't know where getUtility() came from, and if you have more modules from which to import getUtility(), you still run into clashes, and are actually defeating the namespacing which using modules offers. I don't see how that is an argument for "always use specific imports". Personally, I use specific imports when only a small number of names from a module is used, and they're used frequently, otherwise I use general imports.

Personal preference

Posted by tibi at 2008-12-03 18:29
You're perfectly right in what you're saying and I think it comes down to personal preference. My personal preference is guided by the way I work with Pydev and the code I've been interacting with. The main point in my article was that refactoring is easier when you have separate imports, because of the extra checks they provide. I should probably try to expose my points better next time.
Weblog
Atom
RDF
RSS 2.0
Powered by Quills
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: