DekGenius.com
[ Team LiB ] Previous Section Next Section

3.4 Module Imports and Reloads

So far, we've been calling files of code "modules," and using the word "import," without explaining what these terms mean. We'll study modules and larger program architecture in depth in Part V. Because imports are also a way to launch programs, this section introduces enough module basics to get you started.

In simple terms, every file of Python code whose name ends in a .py extension is a module. Other files can access the items defined by a module by importing that module; import operations essentially load another file, and grant access to the file's contents. Furthermore, the contents of a module are made available to the outside world through its attributes, a term we'll define next.

This module-based services model turns out to be the core idea behind program architecture in Python. Larger programs usually take the form of multiple module files, which import tools from other module files. One of the modules is designated as the main or top-level file, and is the one launched to start the entire program.

We'll delve into such architecture issues in more detail later in this book. This chapter is mostly interested in the fact that import operations run the code in a file that is being loaded, as a final step. Because of this, importing a file is yet another way to launch it.

For instance, if we start an interactive session (in IDLE, from a command line, or otherwise), we can run the original script4.py file that appeared earlier with a simple import:

D:\LP-2ndEd\Examples>c:\python22\python
>>> import script4
win32
1267650600228229401496703205376

This works, but only once per session (really, process), by default. After the first import, later imports do nothing, even if we change and save the module's source file again in another window:

>>> import script4
>>> import script4

This is by design; imports are too expensive an operation to repeat more than once per program run. As we'll learn in Chapter 15, imports must find files, compile to byte code, and run the code. If we really want to force Python to rerun the file again in the same session (without stopping and restarting the session), we need to instead call the built-in reload function:

>>> reload(script4)
win32
65536
<module 'script4' from 'script4.py'>
>>>

The reload function loads and runs the current version of your file's code, if you've changed it in another window. This allows you to edit and pick up new code on the fly, within the current Python interactive session. In this session, for example, the second print statement in script4.py was changed in another window to print 2 ** 16, between the time of the first import and the reload call.

The reload function expects the name of an already-loaded module object, so you have to have successfully imported once, before you reload. Notice that reload also expects parenthesis around the module object name, whereas import does not—reload is a function that is called, and import is a statement. That's why we must pass the module name as an argument in parenthesis, and is why we get back an extra output line when reloading. The last output line is just the print representation of the reload call's return value, a Python module object. More on functions in Chapter 12.

3.4.1 The Grander Module Story: Attributes

Imports and reloads provide a natural program launch option, because files are executed by import operations as a last step. In the broader scheme of things, though, modules serve the role of libraries of tools, as we'll learn in Part V. More generally, a module is mostly just a package of names, known as a namespace. And the names within that package are called attributes—variable names that are attached to a specific object.

In typical use, importers gain access to all the names assigned at the top level of a module's file. These names are usually assigned to services exported by the module—functions, classes, variables, and so on—which are intended to be used in other files and other programs. Outside a file, its names can be fetched with two Python statements: import and from, as well as the reload call.

To illustrate, suppose we use a text editor to create the one-line Python module file myfile.py, shown in the following example. This may be one of the world's simplest Python modules (it contains a single assignment statement), but it's enough to illustrate the basics. When this file is imported, its code is run to generate the module's attribute—this file's assignment statement creates a module attribute named title:

title = "The Meaning of Life"

Now, we can access this module's attribute title in other components two different ways. With the import statement, we get back the module as a whole, and qualify the module name by the attribute name to access:

% python                          Start Python.
>>> import myfile                 Run file; load module as a whole.
>>> print myfile.title            Use its attribute names: `.' to qualify.
The Meaning of Life

In general, the dot expression syntax object.attribute lets us fetch any attribute attached to any object, and is a common operation in Python code. Here, we use it to access the string variable title inside module myfile—that is, myfile.title. Alternatively, we can fetch (really, copy) names out of a module with from statements:

% python                          Start Python.
>>> from myfile import title      Run file; copy its names.
>>> print title                   Use name directly: no need to qualify.
The Meaning of Life

As we'll see in more detail later, from is just like an import, with an extra assignment to names in the importing component. Because it also copies names from the imported file, though, we use imports directly without going through the original module name. Technically, from copies a module's attributes, such that they become simple variables in the recipient—we simply refer to the imported string this time as title (a variable) instead of myfile.title (an attribute reference).[3]

[3] Notice that import and from both list the name of the module file as simply myfile, without its .py suffix. As we'll learn in Part V, when Python looks for the actual file, it knows to include the suffix in its search procedure. Again, remember to include the suffix in system shell command lines, but not in import statements.

Whether we use import or from to invoke an import operation, the statements in the module file myfile.py are executed, and the importing component (here, the interactive prompt) gains access to names assigned at the top level of the file. There's only one such name in this simple example—the variable title, assigned to a string—but the concept will be more useful when we start defining more useful objects such as functions and classes in our modules. Such objects become reusable software components accessed by name from one or more client modules.

In practice, module files usually define more than one name to be used in and outside the file. Here's an example that defines three:

a = 'dead'          # Define three attributes.
b = 'parrot'        # Exported to other files
c = 'sketch'
print a, b, c       # Also used in this file

This file, threenames.py, assigns three variables, and so generates three attributes for the outside world. It also uses its own three variables in a print statement, as we see when we run this as a top-level file:

% python threenames.py
dead parrot sketch

When this file is imported elsewhere, all its code runs as usual the first time it is imported (by either an import or from). Clients of this file that use import get a module with attributes; clients that use from get copies of the file's names:

% python 
>>> import threenames                    Grab the whole module.
dead parrot sketch
>>>
>>> threenames.b, threenames.c 
('parrot', 'sketch')
>>>
>>> from threenames import a, b, c       Copy multiple names.
>>> b, c 
('parrot', 'sketch')

The results here are printed in parenthesis, because they are really tuples—a kind of object covered in the next part of this book.

Once you start coding modules with multiple names like this, the built-in dir function starts to come in handy to fetch a list of the names available inside a module:

>>> dir(threenames)
['__builtins__', '__doc__', '__file__', '__name__', 'a', 'b', 'c']

When the dir function is called with the name of an imported module passed in parentheses like this, it returns all the attributes inside that module. Some of the names it returns are names you get "for free": names with leading and trailing double underscores are built-in names that are always predefined by Python, and have special meaning to the interpreter. The variables our code defined by assignment—a, b, and c, show up last in the dir result.

3.4.2 Import and Reload Usage Notes

For some reason, once people find out about running by imports and reloads, many tend to focus on this alone, and forget about other launch options that always run the current version of the code (e.g., icon clicks, IDLE menu options, and command lines). This can lead to confusion quickly—you need to remember when you've imported to know if you can reload, need to remember to use parenthesis in reload (only), and need to remember to use reload in the first place to get the current version of your code to run.

Because of these complications (and others we'll meet later), avoid the temptation to launch by imports and reloads for now. The IDLE Edit/RunScript menu option, for example, provides a simpler and less error-prone way to run your files. On the other hand, imports and reloads have proven to be a popular testing technique in Python classes, so you be the judge. If you find yourself running into a wall, though, stop.

There is more to the module story than exposed here, and you may run into trouble if you use modules in unusual ways at this point in the book; for instance, if you try to import a module file that is stored in a directory other than the one you're working in, you'll have to skip ahead to Chapter 15, and learn about the module search path. For now, if you must import, try to keep all your files in the directory you are working in, to avoid complications.

    [ Team LiB ] Previous Section Next Section