So far, we have used two different versions of the import
statement:
import math print(math.pi)
from math import pi print(pi)
The import
statement is very powerful, however, and we can do all sorts of interesting things with it. In this section, we will look at the different ways in which you can use the import
statement to import modules and packages, and their contents, into your program.
Whenever you create a global variable or function, the Python interpreter adds the name of that variable or function to what is called the global namespace. The global namespace holds all the names that you have defined at the global level. To see how this works, enter the following command into the Python interpreter:
>>> print(globals())
The globals()
built-in function returns a dictionary with the current contents of the global namespace:
{'__package__': None, '__doc__': None, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__loader__': <class '_frozen_importlib.BuiltinImporter'>}
Now, let's define a new top-level function:
>>> def test(): ... print("Hello") ... >>>
If we now print out the dictionary of global names, our test()
function will be included:
>>> print(globals()) {...'test': <function test at 0x1028225f0>...}
As you can see, the name test
has been added to our global namespace.
When something is in the global namespace, you can access it by name from anywhere in your program:
>>> test() Hello
Now, when you use the import
statement, you are adding entries to the global namespace:
>>> import string >>> print(globals()) {...'string': <module 'string' from '/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/string.py'>...}
As you can see, the module that you imported has been added to the global namespace, allowing you to access that module by name, for example like this:
>>> print(string.capwords("this is a test")) This Is A Test
In the same way, if you used the from...import
version of the import
statement, the item you've imported will be added directly to the global namespace:
>>> from string import capwords >>> print(globals()) {...'capwords': <function capwords at 0x1020fb7a0>...}
So now you know what the import
statement does: it adds what you're importing to the global namespace so that you can access it.
Now that we've seen what the import
statement does, let's take a look at the different versions of the import
statement that Python provides.
We've already seen the two most common forms of the import
statement:
import <something>
from <somewhere> import <something>
With the first form, you aren't limited to importing modules one at a time. If you want, you can import multiple modules at once, like this:
import string, math, datetime, random
Similarly, you can import multiple things at once from a module or package:
from math import pi, radians, sin
If you have more items to import than will fit on one line, you can either use line continuation characters () to spread the import across multiple lines, or surround the list of items that you want to import with parentheses. For example:
from math import pi, degrees, radians, sin, cos, tan, hypot, asin, acos, atan, atan2 from math import (pi, degrees, radians, sin, cos, tan, hypot, asin, acos, atan, atan2)
When you import something, you can also change the name of the imported item:
import math as math_ops
In this case, you are importing the math
module under the name math_ops
. The math
module will be added to your global namespace using the name math_ops
, and you can access the math
module's contents using the math_ops
name:
print(math_ops.pi)
There are two reasons why you might want to use the import...as
statement to change the name of something when you import it:
utils
, you might want to use the import...as
statement so that the names are different. For example:from package1 import utils as utils1 from package2 import utils as utils2
Note that you should probably use the import...as
statement sparingly. Every time you change the name of something, you (and anyone reading your code) will have to remember that X
is another name for Y
, which adds complexity and means that you have more things to remember as you write your program. There are certainly legitimate uses for the import...as
statement, but don't overuse it.
You can, of course, combine the from...import
statement with import...as
:
from reports import customers as customer_report from database import customers as customer_data
Finally, you can use a wildcard import to import everything from a module or package in one fell swoop:
from math import *
This adds all the items defined in the math
module into the current global namespace. If you are importing from a package, then all the items defined in the package's __init__.py
file will be imported.
By default, everything in the module (or package) that doesn't start with an underscore character will be imported by a wildcard import. This ensures that private variables and functions won't be imported. If you want, however, you can change what gets included in a wildcard import by using the __all__
variable; this will be discussed in the Controlling what gets imported section later in this chapter.
So far, whenever we've imported something, we've used the full name of the module or package that we want to import from. For simple imports such as from math import pi
, this is sufficient. There are times, however, when this type of importing can be quite cumbersome.
Consider, for example, the complex tree of packages that we looked at in the Packages within packages section earlier in this chapter. Imagine that we want to import a module named slider.py
from within the program.gui.widgets.editor
package:
You could import this module using the following Python statement:
from program.gui.widgets.editor import slider
The program.gui.widgets.editor
part of the import
statement identifies the package where the slider
module can be found.
While this works, it can be quite unwieldy, especially if you have a lot of modules to import or if one part of a package needs to import several other modules from within the same package.
To handle this type of situation, Python supports the concept of relative imports. Using relative imports, you identify what you want to import relative to the current module's position within the tree of packages. For example, imagine that the slider
module wanted to import another module within the program.gui.widgets.editor
package:
To do this, you replace the package name with a .
character:
from . import slider
The .
character is a shorthand for the current package.
In a similar way, imagine that you have a module within the program.gui.widgets
package that wants to import the slider
module from the editor
sub-package:
In this case, your import
statement would look like the following:
from .editor import slider
The .
character still refers to the current location, and editor
is the name of the package relative to this current location. In other words, you are telling Python to look for a package named editor
in the current location, and then import the module named slider
within this package.
Let's consider the opposite situation. Imagine that the slider
module wants to import a module from the widgets
directory:
In this case, you can use two .
characters to mean go up one level:
from .. import controls
As you might imagine, you can use three .
characters to mean go up two levels and so on. You can also combine these techniques to move through the package hierarchy in any way you like. For example, imagine that the slider
module wants to import a module named errDialog
from the gui.dialogs.errors
package:
Using relative imports, the slider
module could import the errDialog
module in the following way:
from ...dialogs.errors import errDialog
As you can see, you can use these techniques to select any module or package anywhere in the tree of packages, relative to your current position in the tree.
There are two main reasons for using relative imports:
import
statements shorter and easier to read. Instead of having to type from
program.gui.widgets.editor import utils
in the slider
module, you can simply type from . import utils
.import
statements to reflect the new package structure.Like anything, relative imports can be overused. Because the meaning of the import
statement depends on the position of the current module, relative imports tend to violate the explicit is better than implicit principle. You can also get into trouble if you attempt to run a module from the command line, as described in the Running modules from the command line section later in this chapter. For these reasons, you should use relative imports sparingly, and stick to fully listing out the entire package hierarchy in your import
statements unless you have a good reason not to.
18.191.237.201