2015-09-24

Import style: Avoid both excessive repetition and the wildcard bug

Let's says that you have a Python module with a function in it. Like this:

mymodule.py:

  def myfunction(name):
      return "Hello %s" % name

You could then use it in another module like this (A):

  import mymodule
  mymodule.myfunction("Dennis")

You could also do this (B):

  from mymodule import myfunction
  myfunction("Denise")

Both approaches have benefits. With approach A, you only have a single line of import for a module, and when you read code using "myfunction", you can see directly that it comes from "mymodule". The downside is the repetition in your code. With Python packages like xml.etree.ElementTree your code might get tiresome to read with the repetition of that long prefix. (And tedious to type.)

With approach B, you don't need to repeat module or package names every time you use stuff in the modules. There are two downsides. If you use a lot of things from the module, you get a pretty noisy import. Maybe something like:

  from xml.etree.ElementTree import Element, ElementTree, SubElement, TreeBuilder, dump, fromstring, iselement, parse, tostring

(Or nine separate import statements if you prefer that.)

The other disadvantage is that you need to look somewhere else in the program to realize where the funtion "iselement" comes from when you run across it in line 735 of some propgram listing.

The best choise is probably this:

import xml.etree.ElementTree as Et

That way, you get a brief import statement, and using Et.dump, Et.parse etc, still makes it easy to figure out where those functions are defined and documented.

Resist the temptation of using wildcards in the import. While it's possible to write "from xml.etree.ElementTree import *", it's a really bad idea. For two reasons:

  1. Someone reading your code will not be able to see where the objects you imported came from.
  2. Your code might suddenly break if the imported module gets a new object which shadows a name you used. This is really nasty, since the bug might appear when someone does a regular upgrade on his computer. Nothing changed in your code, but a library your code used got updated.