As programs get larger and larger, it makes more and more sense to split one large file into a number of smaller files. This keeps the code nice and tight and it also makes modification of the code easier, especially if the project is being developed simultaneously by a number of different people.
In Python you have the ability to split up a program into a number of individual files called modules. Modules can then be imported into your existing scripts, providing you with access to the functions, objects, and classes you have defined within each module. This concept is similar to the modules used in Perl and to the libraries and class definitions used in Visual Basic, C/C++, and many other languages.
This chapter looks at how to import modules from the standard library and those libraries you create yourself. It also explains how to create module packages, which are tested groups of modules that can be loaded either on an individual basis or as one complete package, depending on how they are configured.
Importing a Module
In Python you import the module into a script you are importing information about how to use the functions, objects, and classes within the module, rather than importing the different entities themselves into the script. This will become clearer when you understand the different methods for importing modules and what happens when you use the import statement.
Importing an Entire Module
To import, that is, to give yourself access to the functions, objects, and classes within a given module, you use the import statement:
The import statement in Python does three things
•It creates a new namespace to hold all the objects defined within the given module.
•It executes the code in the module within the confines of the given namespace.
•It creates a name within the caller that refers to the module’s namespace.
In the preceding example, a new namespace ftplib was created, the ftplib.py file in the Python library directory was found and executed within the ftplib namespace, and then an object called ftplib was created within the namespace of the current module_in this case the main script. See “Module Loading and Compilation” later in this chapter for information on how Python searches for modules.
You can also import multiple modules simultaneously by separating each module name by a comma in the import statement:
import os, sys, getopt, ftplib
Each module name is interpreted individually so the preceding example is equivalent to the following statements:
import os import sys import getopt import ftplib
If you are going purely for clarity, then writing an import statement for each module being imported is preferred. In most situations, importing several modules in one import statement works just as well, and most programmers can probably spot which modules have been imported just by reading the rest of the code.
Importing a Module Under an Alias
An extension of the basic import method made available in Python 2.0 is the ability to import a module within a namespace different than the default namespace selected by the module’s apparent name. For example, you can import the ftplib module as simple ftp using
import ftplib as ftp
Now all calls to the ftplib module must be identified within the ftp namespace. Using aliases can be a great way to test a new version of a module without upsetting the original. For example, imagine you’ve got two modules where the stable version is mylib and the development version is newmylib. You could change references in your test scripts to
import newmylib as mylib
No changes need to be made to the rest of the script for it to work – provided that your new module doesn’t break any of the APIs.
Importing Specific Module Entities
To import specific functions and objects from a given module, use the from … import…. statement. For example, to import the objects foo and bar from the module foobar, use the following statement:
from foobar Import foo, bar
The major difference between the preceding statement and the import … statement is that the objects that you import become available within the current namespaces, so you no longer have to specify them as explicitly. For example, the following script is now valid:
from Foobar import foo, bar foo() bar()
To import everything from a given module into the current namespace, use*:
from Foobar import*
Reloading a Module
You can reload a module that has previously been loaded by calling the built-in function reload(). This forces Python to reinterpret and import the module again, as in the following example:
import foo ..... reload (foo)
However, the reload function only reloads Python modules; those modules that rely on a C/C++ dynamic library will not work. Also, reloading does not modify any existing objects that use the methods defined in the module they will continue to use the old methods until they are destroyed. See Chapter 8 for more information.
Module Search Path
When you load a module, the Python interpreter searches a standard set of directories to find the module that you specify. The path is system and installation specific, but you can find the current list of directories using sys.path. The following is the list of directories under a Solaris 8/x86 installation of Python 2.0:
['', 'development: application: 2.0', 'development: applications: python 2.0:mac:plugins', 'development: applications: python 2.0:mac:lib', 'development: applications: python 2.0:mac:lib:lib-toolbox', 'development: applications: python 2.0:mac:lib:lib-sriptpackages', 'development: applications: python 2.0:lib', 'development: applications: python 2.0:extensions:img:mac', 'development: applications: python 2.0:extensions:img:lib', 'development: applications: python 2.0:extensions:numerial:lib', 'development: applications: python 2.0:extensions:numerical:lib:packages', 'development: applications: python 2.0:extensions:imaging:pil', 'development: applications: python 2.0:lib:lib-tk', 'development: applications: python 2.0:lib:site-package']
The ‘ ‘ in both directory lists refers to the current directory.
To add directories to the module search path, you can add them to sys.path, for example to add /lib/python to the search list:
import sys sys.path.append('./lib/python')
Now all future import statements will not only search the standard libraries, but also the directory you’ve just added.
To insert new directories before the standard search path, use the insert() method to add the directory to the start, rather than to the end of the list:
Alternatively, on platforms that support environment variables (Windows, Unix, BeOS, etc.), you can add directories to the PYTHONPATH variable before execution.
Module Loading and Compilation
When you request to load a particular module, the Python interpreter looks in the following places for the module you want to load:
•Programs/modules written in Python
•C or C++ extensions that have been compiled into shared libraries or DLLs
•Packages containing a collection of modules (see “Packages” later in this chapter)
•Built-in modules written in C that have been linked into the Python interpreter
What Python is actually seeking bf files within the Python library search path (in the following order, assuming a module called foo):
1. A directory defining a package called foo.
2. A compiled extension or library named foo.so, foomodule.so, foomodule.sl, or foomodule.dll. The exact interpretation, of course, depends on the host operating system. Not all operating systems support dynamically loadable modules.
3.A file called foo.pyo (assuming that the –O option has been used).
4. A file called foo.pyc (the precompiled bytecode version of foo.py).
5. A file called foo.py.
6. A built-in module called foo.
When Python finds the file foo.pyr, the timestamp is checked against foo.py. If fon.py is newer, then the file is compiled and the compiled bytecode for the module is written into foo.pyc. Python therefore always attempts to lead a precompiled bytecode for modules loaded through import Modules execute as a script are not precompiled and stored in any way.
If the –O command – line option is in effect, Python loads an optimized form of the precompiled bytecode, as stored in .pyo files. These are identical in content to the .pyc file except that the line numbers, assertions, and other debugging information that can be used to trace the execution of the module are removed.
If, after trying to load all these different components, one still cannot be found, then the ImportError exception is raised.
Tricks for Importing Modules
Beyond the basic mechanics described hen. Python also supports number different techniques and tricks that you can use to import modules within a Python script. Most of these techniques should only be used by expert programmers. Other techniques allow you to be more flexible in your approach to using modules.
Using import in a Script
The normal mode of operation is to import the modules you want to use at the top of the script, for example:
import os,sys.getopt # Start processing def start(): ...
The Python interpreter only executes the import statement at the point at which it sees the statement within the code during the execution process. This allows you to execute import statements just as you would any other piece of Python code, including within the confines of an if or other control statement:
if (module == 'os'): import os else: import sys
This technique is actually used by modules like os that load a platform-specific module such as posix or mac, depending upon the host on which the Python interpreter is running. It’s also perfectly legal to load modules only when a function is actually called, as in the following example:
def sendmymail(): import smtplib
For all this flexibility, however, you cannot import a module using a variable or string as the module name without using the exec statement, as in the following example:
module ='os' exec 'import '+module
See Chapter 8 for more information on the exec statement.
Trapping import Statements
The import statement raises an ImportError exception if a module fails to load correctly. You can safely trap a failed module load directly within the script, allowing you to exit graciously, as in the following example:
try: import mymodule except ImportError: print "whoa! We seem to be missing a module we require here" Import sys sys.exit( )
Identifying a Module or a Script
Each module defines a variable, __name__, that contains the name of the module. You can use this variable as a way to determine which module a particular piece of code is executing within. However, it also becomes a handy way to determine whether a given module is running as a script or whether it has been imported. Modules running as scripts set __name__ to__ main_, and you can test for this:
If __name__ ==' __main__': #Work as a script else: #Work an a module
Note that __name__ returns the original name of the module rather than the alias name specified when using the import… as import technique. If you use the preceding trick, this won’t make any difference, but be careful using the module name internally as a key to its name when imported.
Although this particular trick shouldn’t be used to affect the functions or classes defined within the module, it can and often is used as a handy testing mechanism for a module. When you run the module as a script, it tests itself, but when the module is imported, it just defines the functions. This saves you from having a separate test script and aids Python’s code reuse because each module can be used as both script and library addition.
If you check any of the standard modules that come with Python you’ll probably find such a block. For example, running the smtplib module as a script allows you to send an e-mail message:
$ python satplib.py From: [email protected] To: [email protected] Enter message, end with ^D: Hello Dopplegenger! Message length is 20 Send: 'ehlo twinsol\o15\012' reply: '250-twinsol.mchome.com Hello localhost [127.0.0.1], pleased To meet you \015\012' Reply:'250-ENHANCEDSTATUSCODES\015\012' Reply: '250-EXPN\015\012' ...
The output in the preceding example has been trimmed for clarity, but you can see the effect. Importing smtplib as a module has no effect– you import the module and it functions as normal.
Packages in Python allow a set of modules to be grouped under a common package. name. Programmers from a Perl background might expect the statement
to search the various directories for the file package/module.py automatically, but it doesn’t. For the import statement to work in this way you must have previously set up a package and its corresponding directory structure.
A package is defined by creating a directory with the same name as the package and then creating the file __init__.py within that directory. This file contains the necessary instructions to the Python interpreter to allow the importing of modules and module groups within the package. For example, the following directory structure shows the layout of a project called MediaWeb which, as a network management tool, has been placed in the Net directory:
Net/ __init__ •py MediaWeb/ __init__•py Weather•py Weblog•py Systemlog•py
Now, from within Python, you can import modules from this structure in a number of ways. The statement
imports the submodule Weather from the Net/MediaWeb directory. As with a other import statements, you must refer to functions in this module explicitly, I.e..,
from Not .Mediakob import Weather
imports the same module. Weather, but without the package prefix, allowing you to use Weather.report().
From Net.MediaWeb.Weather import report
imports report into the local namespace, enabling you to call it using report(). In each case, the code in_init_.py is executed in order to perform any package specific initialization. All the __init__.py files are processed as they are seen within the import process. For example, importing Net.MediaWeb.Weather would execute Net/ __init__.py and Net/MediaWeb/__init__.py.
The contents of each__init__. py file are entirely up to you they may be empty, in which case nothing happens except to import the module you’ve selected. But they must exist for the directory nesting to work as you would expect it within Perl. On the other hand, you may want to enfonce certain options. For example, the statement
does not automatically force Python to import the contents of the Net/MediaWeb directory and neither does the statement
From Net.MediaWeb Import*
In these examples you can do one of two things. In the first example you may want to put the following statements into the Net/MediaWeb/_init_.py file:
# Net/Mediaweb/__init__.py import Weather, Weblog
In the second example, you can use the_all_attribute within the __init__.py file. This should be initialized with a list of modules that you want to import:
# Net/Medialleb/__init__.py __all__ =['weather', 'Weblog']
Creating a Module
Creating a new module in Python is as easy as writing the original script. Any file or script that you have created in Python is immediately available as a module without making any modifications to the code. In fact, apart from copying the file into a standard location to make it readily available, there’s nothing else you need to do. For example, imagine you’ve create a small script called mymath.py that defines a single function, add():
def add(a,b): return a+b print add(1,1)
You can import the mymath.py file and make use of the add() function within another script just by importing the mymath file and calling the function:
import mymath print mymath.add(2,2)
The import statement automatically looks for the file mymath.py and then creates a new namespace and imports the add() function into that namespace. Furthermore, you can also explicitly import add() into the current namespace using the statement
from mymath import add
It really is that simple!!
Because of this flexibility, all of the code and functions that you write and create in Python are available to all the other scripts and modules that you create without any modifications. All of your code is immediately reusable, and you don’t have to worry about deliberately creating a module or doing anything special to make your code reusable.
In comparison, to create a flexible module MyModule in Perl, you’d have to add the following preamble to a file called MyModule.pm:
package MyModule; require Exporter; use vars qu/@ISA EEXPORT/; @ISA - qw/Exporter/; @EXPORT = qw/add/;
You’d also have to update @EXPORT for each entity that you want to explicitly export, and append a “true” value to be returned by the file when it is imported. In comparison to Python, Perl is quite fussy and it’s possible to stop a module from working entirely by getting this preamble wrong.