Importing `*` in Python

This post discusses Python?s from <module> import * and from <package> import *, how they behave and why it may be (is!) a bad idea to use them.

Importing `*` from a module

from <module> import * means ?I want access to all the names in <module> that I?m meant to have access to?. So, let?s say we have the following something.py:

# something.pypublic_variable = 42_private_variable = 141def public_function(): print(“I’m a public function! yay!”)def _private_function(): print(“Ain’t nobody accessing me from another module…usually”)class PublicClass(object): passclass _WeirdClass(object): pass

In the Python Interpreter, we can execute from something import * and see the following:

>>> from something import *>>> public_variable42>>> _private_variable…NameError: name ‘_private_variable’ is not defined>>> public_function()”I’m a public function! yay!”>>> _private_function()…NameError: name ‘_private_function’ is not defined>>> c = PublicClass()>>> c<something.PublicClass object at …>>>> c = _WeirdClass()…NameError: name ‘_WeirdClass’ is not defined

So, from something import * imports all the names from something other than the names that start with an _; because they are conventionally meant to be private.

Ermm, that?s not too bad! Is that `__all__`?

What?s not mentioned above is what __all__ is. __all__ is a list of strings defining what symbols in a module (or a package as we?ll see later) will be exported when from <module> import * is used on the module. If we don?t define __all__ (we didn?t in something.py above), the default behaviour of import * is to import all names except those beginning with an underscore (_). Again, since conventionally an underscore is used to say a symbol is private, that all makes sense. Let?s see what happens when we define our own __all__ in something.py:

# something.py__all__ = [‘_private_variable’, ‘PublicClass’]# The rest is the same as beforepublic_variable = 42_private_variable = 141def public_function(): print(“I’m a public function! yay!”)def _private_function(): print(“Ain’t nobody accessing me from another module…usually”)class PublicClass(object): passclass _WeirdClass(object): pass

Now, we expect from something import * to only import the _private_variable and PublicClass names:

>>> from something import *>>> public_variable…NameError: name ‘public_variable’ is not defined>>> _private_variable0>>> public_function()…NameError: name ‘public_function’ is not defined>>> _private_function()…NameError: name ‘_private_function’ is not defined>>> c = PublicClass()>>> c<something.PublicClass object at …>>>> c = _WeirdClass()…NameError: name ‘_WeirdClass’ is not defined

What about packages?

When importing * from a package, __all__ does approximately the same thing as for modules, except it deals with modules within the package (in contrast to specifying names within the module). So __all__ specifies all modules that shall be loaded and imported into the current namespace when we use from <package> import *.

However, the difference is, when you omit the declaration of __all__ in a package?s __init__.py, the statement from <package> import * will not import anything at all (not entirely true; Read this for the truth).

But, why is this bad?

Before proceeding, in your Python Interpreter, import this and read The Zen of Python again (read it to your kids every night before they sleep too).

Explicit is better than implicit.

from <module> import * is not explicit. It isn?t telling us anything about what we?re importing or what names we?re bringing into our namespace. It would be much better to explicitly specify and import everything we need; that way, a reader (most likely your future self) won?t be confused about where a variable/function/class/etc. used in the code comes from, which leads us to:

Readability counts.

Even if a lot of names are required, it?s still much clearer to import them one by one, explicitly. Use PEP 328:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text, LEFT, DISABLED, NORMAL, RIDGE, END)

You now know exactly what you have in your namespace and a quick ctrl+f (figuratively speaking) can tell you where a name has come from.

Also, you are always at risk if/when the module/package author decides to change the contents of the list (add/remove stuff to/from it). Then, either:

  1. The author has removed a string from __all__. If your code was using that name, your code will raise a NameError and it?ll be harder to find out why.
  2. The author has added [many] new strings to __all__. You may not need all/any of the new names and you?re just bloating your namespace with stuff you don?t care about. They may even shadow some other names without you realising.

Of course, sometimes it may be useful or necessary to import * from modules and/or packages. However, it?s best to make sure you really have to before doing it. In my experience, this construct is usually used as a result of laziness more than anything else.

12

No Responses

Write a response