CHAPTER 9
A Python module is a file that has a .py extension. These can be used to implement a set of attributes (variables), methods (functions), and classes (types). You can include a module in another Python program simply by using the import statement followed by the module name. To import a module named time, include import time within your Python program. You can now access the methods within the time module by calling time.method_name() or attributes, sometimes called variables, by calling time.attribute_name. The following code listing is an example using the asctime() method and the timezone attribute from the time module. The timezone attribute includes the number of seconds between UTC and the local time.
Code Listing 263
import time print(time.asctime()) print(time.timezone) |
Output:
Code Listing 264
Tue Aug 25 14:28:03 2015 21600 |
Whenever you import module_name, all of the methods in that module will be available as module_name.method_name(). If you opt to use a single method in a module you can import just that method using the from module_name import method_name syntax. Now the method can be accessed in your program by name. Instead of calling module_name.method_name(), you can now simply call method_name().
Code Listing 265
from time import asctime print(asctime()) |
Output:
Code Listing 266
Tue Aug 25 14:28:03 2015 |
It is possible to do the same thing using module attributes and classes. If you are looking to import more than one item from a module you can create a separate from module_name import method_name line for each one. You can also opt to provide a comma separated list like this: from module_name import method_name1, method_name2, method_nameN. Let's import the asctime() and sleep() methods from the time module. The sleep() method pauses the execution of your program for an allotted number of seconds.
Code Listing 267
from time import asctime, sleep print(asctime()) sleep(5) print(asctime()) |
Output:
Code Listing 268
Tue Aug 25 14:28:03 2015 Tue Aug 25 14:28:08 2015 |
One of the primary benefits of importing either a single method or list of methods from a module is that you can access it directly by name without having to precede it with the module name. For example, sleep(5) versus time.sleep(5). If you want to be able to access everything from a module, you could use an asterisk instead of a list of methods to import. However, this is not a practice I recommend. It is worth mentioning here only because you will see it used from time to time. The main reason it is best to avoid this approach is that you run the risk of overriding an existing function or variable if you import everything into your program. Also, when you import multiple methods using an asterisk, you will find it hard to determine what exactly came from where.
Code Listing 269
from time import * print(timezone) print(asctime()) sleep(5) print(asctime()) |
Output:
Code Listing 270
21600 Tue Aug 25 14:28:03 2015 Tue Aug 25 14:28:08 2015 |
You can use the built-in dir() function to discover which attributes, methods, and classes exist within any one module.
Code Listing 271
>>> import time >>> dir(time) ['_STRUCT_TM_ITEMS', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset'] |
Keep in mind that you can always view the default module search path by examining sys.path. Whenever you supply an import module_name statement, Python will look for the module in the first path on the list. If Python cannot find it then the next path will be examined and so on. This will continue either until the module is found or until all of the module search paths are completely exhausted. The module search path may include zip files as well as directories. Python will search within the zip file for a matching module as well. It is important to note that the default module search path will vary depending on your installation of Python, the Python version, and the operating system. The following code listing is an example from a Python installation on a Mac.
Code Listing 272
# show_module_path.py import sys for path in sys.path: print(path) |
Output:
Code Listing 273
/Users/david /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4 /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages |
The show_module_path.py file was located in /Users/david when I first executed python3 show_module_path.py. Notice that /Users/david is listed first in the module search path. The other directories were decided by the Python installation.
If you want to ask Python to search other locations for modules you will need to manipulate the module search path. There are two ways that you can do this. The first method is to modify sys.path just as you would any other list. For example, you can append directory locations by using a string data type.
Code Listing 274
import sys sys.path.append('/Users/david/python') for path in sys.path: print(path) |
Output:
Code Listing 275
/Users/david /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4 /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages /Users/david/python |
You are also able to manipulate the PYTHONPATH environment variable. This variable acts in a very similar manner to the PATH environment variable. On Mac and Linux systems, PYTHONPATH can be populated with a list of directories separated by colons. On Windows systems the PYTHONPATH environment variable requires the use of a semicolon in order to separate the list of directories. The directories listed in PYTHONPATH are inserted after the directory where the script resides and before the default module search path.
In the following example, /Users/david is the directory where the show_module_path.py Python program resides. The /Users/david/python and /usr/local/python/modules paths are included in PYTHONPATH. The export command makes PYTHONPATH available to programs started from the shell.
Code Listing 276
[david@mac ~]$ export PYTHONPATH=/Users/david/python:/usr/local/python/modules [david@mac ~]$ pwd /Users/david [david@mac ~]$ python3 show_module_path.py /Users/david /Users/david/python /usr/local/python/modules /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4 /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages [david@mac ~]$ |
If you are unable to find a module within the search path, an ImportError exception will be raised.
Code Listing 277
import say_hello |
Output:
Code Listing 278
Traceback (most recent call last): File "test_say_hello.py", line 1, in <module> import say_hello ImportError: No module named 'say_hello' |
As we’ve worked through previous examples, we have been using the time module which comes included with Python. In fact, Python is supplied with a large library of modules for you to take advantage of. I would highly recommend that you take some time to really look at what the Python standard library has to offer before you even think of writing any of your own code. For example, if you are looking to read and write CSV (comma-separated values) files, don’t waste your time creating something from scratch when it already exists. Just use Python's pre-existing csv module. Are you looking to enable logging in your program? Well, there’s a logging module which can help you do that. Do you want to make an HTTP request to a web service and then parse the JSON response? Try using the urllib.request and json modules. To explore these modules and more, check out the list of what is available in the Python Standard Library located at https://docs.python.org/3/library/.
Now, let's use the exit() method from the sys module to cleanly terminate your program if it detects an error. In the following example, the file test.txt is opened. If the program encounters an error while the file is opening, the code block following except: will execute. If the reading of test.txt is mandatory for the remaining code to function correctly, there is no need to continue. The exit() method can accept an exit code as an argument. If no exit code is provided, 0 will be used. By convention, when an error causes a program to exit, a non-zero exit code is expected.
Code Listing 279
import sys file_name = 'test.txt' try: with open(file_name) as test_file: for line in test_file: print(line) except: print('Could not open {}.'.format(file_name)) sys.exit(1) |
Just as Python has a library of its own reusable code, so can you. It’s quite simple to create your own module. Just remember that in its least complex form, modules are files that have a .py extension. Simply create a Python file with your code and import it from another Python program.
The following code listing is the contents of say_hello.py.
Code Listing 280
def say_hello(): print('Hello!') |
Note how you can import and use the say_hello module. To call the say_hello() method within the say_hello module, use say_hello.say_hello().
Code Listing 281
import say_hello say_hello.say_hello() |
Output:
Code Listing 282
Hello! |
The following sample is another simple module called say_hello2. Here are the contents of say_hello2.py.
Code Listing 283
def say_hello(): print('Hello!') print('Hello from say_hello2.py!') |
Let's find out what happens when you import the say_hello2 module.
Code Listing 284
import say_hello2 say_hello2.say_hello() |
Output:
Code Listing 285
Hello from say_hello2.py! Hello! |
So what happened? Well, when say_hello2 is imported its contents are executed. First, the say_hello() function is defined. From there the print function is executed. In this way Python enables you to create programs that behave one way when they are executed, and another way when they are imported. If you would like to be able to reuse functions from an existing Python program, but have no desire to execute the main program, you can account for that.
Whenever a Python file is executed as a program, the special variable __name__ will be set to __main__. Notice that there are two underscore characters in the names of these special variables. In instances where it is imported, the __name__ variable will not be populated. Ultimately you can use this to control the behavior of your Python program. The following code sample is the say_hello3.py file.
Code Listing 286
def say_hello(): print('Hello!') def main(): print('Hello from say_hello3.py!') say_hello() if __name__ == '__main__': main() |
Whenever it is executed as a program, the code block following if __name__ == '__main__' will be executed. In the following example it simply calls main(). This is a very common pattern and you will see this within many Python applications. When say_hello3.py is imported as a module nothing will be executed unless explicitly called from the importing program.
Code Listing 287
[david@mac ~]$ python3 say_hello3.py Hello from say_hello3.py! Hello! [david@mac ~]$ |
Python modules are files that have a .py extension and are capable of implementing a set of variables, functions, and classes.
Use the import module_name syntax to import a module.
The default module search path will be determined by your Python installation.
In order to manipulate the module search path modify sys.path or set the PYTHONPATH environment variable.
The Python standard library is a sizeable collection of code that can be reused within your Python programs.
Use the dir() built-in function to find out exactly what exists within a module.
You can establish your own personal library by writing your own modules.
You can influence how a Python program behaves based on whether it is run interactively or imported by checking the value of ___name___.
The if __name__ == '__main__': syntax is a common Python idiom.
Update the "Pig Speak" program we discussed in Chapter 1 so that it can be imported as a module or run directly. When run as a program it should prompt for input, as well as display a pig "saying" what was provided by the user. Place the input provided by the user inside a speech bubble. This speech bubble can be expanded or contracted to fit around the input provided by the user.
Sample output when run interactively:
Code Listing 288
______________________ < Pet me and I will oink > ---------------------- / ^..^ / ~( ( oo ) ,, ,, |
From here, create a new program called pig_talk.py that imports the pig_say module. Try using a function from the pig_say() module to display a variety of messages to the screen.
Sample output when used as a module:
Code Listing 289
________ < Feed me. > -------- / ^..^ / ~( ( oo ) ,, ,, ____________ < Oink. Oink. > ------------ / ^..^ / ~( ( oo ) ,, ,, |
Below are the contents of pig_say.py:
Code Listing 290
def pig_say(text): """Generate a picture of a pig saying something""" text_length = len(text) print(' {}'.format('_' * text_length)) print(' < {} >'.format(text)) print(' {}'.format('-' * text_length)) print(' /') print(' ^..^ /') print('~( ( oo )') print(' ,, ,,') def main(): text = input('What would you like the pig to say? ') pig_say(text) if __name__ == '__main__': main() |
Below are the contents of pig_talk.py:
Code Listing 291
import pig_say def main(): pig_say.pig_say('Feed me.') pig_say.pig_say('Oink. Oink.') if __name__ == '__main__': main() |
__main__ documentation: https://docs.python.org/3/library/__main__.html
Idioms and Anti-Idioms in Python: https://docs.python.org/3.1/howto/doanddont.html
Linux for Beginners: http://www.linuxtrainingacademy.com/linux.
PYTHONPATH documentation: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH
The Python Standard Library: https://docs.python.org/3/library/
The sys module: https://docs.python.org/3/library/sys.html
sys.path documentation: https://docs.python.org/3/library/sys.html#sys.path
virtualenv documentation: https://pypi.python.org/pypi/virtualenv