Python Importing
I would still love to hear your feedback in the comments below. Enjoy!
When you start to work on even rudimentary Python application, the first thing you usually do is import some package you’re using. There are many ways to import packages and modules - some are extremely common (found in pretty much every Python file ever written) and some less so. In this post I will cover different ways to import or reload modules, some conventions regarding importing, import loops and some import easter-eggs you can find in Python.
Cheat Sheet
Different Ways to Import
1. import foo
The basic Python import. The statement import foo looks for a foo model, loads it into memory and creates a module object called foo. How does Python knows where to find the foo module?
When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable
sys.path
.sys.path
is initialized from these locations:
- the directory containing the input script (or the current directory).
PYTHONPATH
(a list of directory names, with the same syntax as the shell variablePATH
).- the installation-dependent default.
If there is a bar
object (which could be anything from a function to a submodule) it can be accessed like a member: foo.bar
. You can also import several modules in one line by doing import foo, bar
, but it is considered good practice to put each import in a single line.
2. import foo.bar
This makes foo.bar
available without importing other stuff from foo
. The difference from import foo
is that if foo
also had a baz
member, it won’t be accessible.
3. from foo import bar
This statement imports bar
which could be anything that is declared in the module. It could be a function definition, a class (albeit a not-conventionally-named class) or even a submodule (which make foo a package). Notice that if bar
is a submodule of foo
, this statement acts as if we simply imported bar
(if it was in Python’s search path). This means that a bar
object is created, and its type is 'module'
. No foo
object is created in this statement.
Multiple members of foo
can be imported in the same line like so:
4. from foo import bar, baz
The meaning of this is pretty intuitive: it imports both bar
and baz
from the module foo
. bar
and baz
aren’t neccessarily the same types: baz could be a submodule and bar could be function, for that matter. Unlike importing unrelated modules, it’s perfectly acceptable to import everything from one module in the same line.
5. from foo import *
Sometimes foo contains so many things, that it becomes cumbersome to import them manually. Instead, you can just import * to import them all at the same time. Don’t do this unless you know what you’re doing! It may seem convenient to just import * instead of specific members, but it is considered bad practice. The reason is that you are in fact “contaminating” your global namespace. Imagine that you do import *
on a package where someone unwittingly declared the following function:
When you do import *
, this list definition will override the global, built-in list type and you’ll get very, very unexpected errors. So it’s always better to know exactly what you’re importing. If you’re importing too much stuff from a certain package, you can either just suck it up or just import the package itself (import foo) and use the foo qualifier for every use. An interesting good use for import *
is in Django settings file hierarchy. It’s convenient there because you actually do want to manipulate the global namespace with imported settings.
6. from foo import bar as fizz
This one is far less common than what we covered so far, but still well known. It acts like from foo import bar
, except instead of creating a bar
object, it creates a fizz
module with the same meaning. There are two main reasons to use this kind of statement: the first is when you’re importing two similarly named objects from two different modules. You then use import as to differentiate them, like so:
The other reason, which I’ve seen used a few times is when you import a lone-named function (or class) and use it extensively throughout your code and want to shorten its name.
7. from .foo import bar
Well, this escalated quickly.
This one is pretty rare and a lot of people are completely unaware of it. The only difference in this statement is that it uses a modified search path for modules. Namely, instead of searching the entire PYTHONPATH
, it searches in the directory where the importing file lives. So if you have two files called fizz.py
and foo.py
, you can use this import in fizz, and it will import the correct file, even if you have another foo
module in your PYTHONPATH
. What is this good for? Well, sometime you create modules with generic names like common
, but you might also have a common
package in the base of your project. Instead of giving different names, you can explicitly import the one closest to you. You can also use this method to load modules from an ancestor in the directory tree by putting several dots. For example, from ..foo import Foo
will search one directory up, from ...foo import Foo
will search two directories up, etc.
8. foo = __import__("foo")
Ever wondered how can you import a module dynamically? This is how. Obviously you wouldn’t use it with an explicit string, but rather with a variable of some kind. Also notice that you have to explicitly assign the imported module to a variable, or you won’t have access to its attributes.
9. reload(foo)
This statement does exactly what it looks like. It reloads the foo
module. It’s pretty useful when you have a console open playing with a bit of code you’re tweaking and want to continue without resetting your interpreter.
Note: If you used from foo import bar, it’s not enough to reload foo
for bar
to update. You need to both reload foo
and call from foo import bar
again.
Import Loops
An import loop would occur in Python if you import two or more modules in a cycle. For example, if in foo.py
you would from bar import Bar
and in bar.py
you from foo import Foo
, you will get an import loop:
When this happens to you, the solution is usually to move the common objects from foo.py
and bar.py
to a different file (say common.py
). However, sometime there’s actually a real loop of dependencies. For example, a method in Bar
needs to create a Foo
instance and vice versa. When the dependency is in a limited scope, you should remember that you can use the import
command wherever you want. Putting imports at the top of the file is the common convention, but sometimes you can solve import loops by importing in a smaller scope, like in a method definition.
Easter Eggs
What fun would an easter egg be if you didn’t try it by yourself? Try these and have fun!
Discuss this post at the comment section below.Follow me on Twitter and Facebook