Importing modules - Python in easy steps (2014)

Python in easy steps (2014)

5

Importing modules

This chapter demonstrates how to use Python modules in your programs.

Storing functions

Owning function names

Interrogating the system

Performing mathematics

Calculating decimals

Telling the time

Running a timer

Matching patterns

Summary

Storing functions

Python function definitions can, usefully, be stored in one or more separate files for easier maintenance and to allow them to be used in several programs without copying the definitions into each one. Each file storing function definitions is called a “module” and the module name is the file name without the “.py” extension.

Functions stored in the module are made available to a program using the Python import keyword followed by the module name. Although not essential, it is customary to put any import statements at the beginning of the program.

Imported functions can be called using their name dot-suffixed after the module name. For example, a “steps” function from an imported module named “ineasy” can be called with ineasy.steps().

Where functions stored in a module include arguments, it is often useful to assign a default value to the argument in the definition. This makes the function more versatile as it becomes optional for the call to specify an argument value.

imageStart a new Python module by defining a function that supplies a default string value to its argument for display
def purr( pet = ‘A Cat’ ) :

print( pet , ‘Says MEOW!’ )

image

cat.py

imageNext, add two more function definitions that also supply default string values to their arguments for display
def lick( pet = ‘A Cat’ ) :

print( pet , ‘Drinks Milk’ )

def nap( pet = ‘A Cat’ ) :

print( pet , ‘Sleeps By The Fire’ )

imageNow, save the file as “cat.py” so the module is named “cat”

imageStart a new Python script with a statement to make the “cat” module functions available
import cat

image

kitty.py

imageNext, call each function without supplying an argument

cat.purr()

cat.lick()

cat.nap()

imageNow, call each function again and pass an argument to each, then save the file

cat.purr( ‘Kitty’ )

cat.lick( ‘Kitty’ )

cat.nap( ‘Kitty’ )

imageStart another Python script by making the “cat” module functions available once more

import cat

image

tiger.py

imageThen, request the user enters a name to overwrite the default argument value

pet = input( ‘Enter A Pet Name: ‘ )

imageFinally, call each function, passing the user-defined value as the argument

cat.purr( pet )

cat.lick( pet )

cat.nap( pet )

imageSave the file in your scripts directory then open a Command Prompt window there and run these programs - to see output from the imported module

image

image

You can create an alias when importing a module using import as keywords. For example import cat as tom allows you to use tom as the function prefix in calls.

Owning function names

Internally, each Python module and program has its own “symbol table” which is used by all functions defined in that context only. This avoids possible conflicts with functions of the same name in another module if both modules were imported into one program.

When you import a module with an import statement, that module’s symbol table does not get added to the program’s symbol table - only the module’s name gets added. That is why you need to call the module’s functions using their module name prefix. Importing a “steps” function from a module named “ineasy” and another “steps” function from a module named “dance” means they can be called without conflict as ineasy.steps() and dance.steps().

image

Where you import individual function names, the module name does not get imported - so it cannot be used as a prefix.

Generally, it is preferable to avoid conflicts by importing the module name and calling its functions with the module name prefix but you can import individual function names instead with a from import statement. The module name is specified after the from keyword, and functions to import are specified as a comma-separated list after the import keyword. Alternatively, the * wildcard character can be specified after import to import all function names into the program’s own symbol table. This means the functions can be called without a module name prefix.

imageStart a new Python module by defining a function that supplies a default string value to its argument

def bark( pet = ‘A Dog’ ) :

print( pet , ‘Says WOOF!’ )

image

dog.py

imageNext, add two more function definitions that also supply default string values to their arguments

def lick( pet = ‘A Dog’ ) :

print( pet , ‘Drinks water’ )

def nap( pet = ‘A Dog’ ) :

print( pet , ‘ Sleeps In The Sun’ )

imageSave the file as “dog.py” so the module is named “dog”.

imageStart a new Python script with a statement to make individual “dog” module functions available

from dog import bark , lick , nap

image

pooch.py

imageNext, call each function without supplying an argument

bark()

lick()

nap()

imageNow, call each function again and pass an argument value to each then save the file

bark( ‘Pooch’ )

lick( ‘Pooch’ )

nap( ‘Pooch’ )

imageStart another Python script by making all “dog” module functions available

from dog import *

image

fido.py

imageThen, request the user enters a name to overwrite the default argument value

pet = input( ‘Enter A Pet Name: ‘ )

imageFinally, call each function, passing the user-defined value as the argument

bark( pet )

lick( pet )

nap( pet )

imageSave the file in your scripts directory then open a Command Prompt window there and run these programs - to see output from the imported functions

image

image

For larger programs you can import modules into other modules to build a module hierarchy.

Interrogating the system

Python includes “sys” and “keyword” modules that are useful for interrogating the Python system itself. The keyword module contains a list of all Python keywords in its kwlist attribute and provides an iskeyword() method if you want to test a word.

You can explore the many features of the “sys” module and indeed any feature of Python using the Interactive Mode help system. Just type help() at the >>> prompt to start the help system then type sys at the help> prompt that appears.

Perhaps most usefully, the “sys” module has attributes that contain the Python version number, interpreter location on your system, and a list of all directories where the interpreter seeks module files - so if you save module files in any of these directories you can be sure the interpreter will find them.

imageStart a new Python script by importing the “sys” and “keyword” modules to make their features available
import sys , keyword

image

system.py

imageNext, add a statement to display the Python version
print( ‘Python Version:‘ , sys.version )

imageNow, add a statement to display the actual location on your system of the Python interpreter
print( ‘Python Interpreter Location:’ , sys.executable )

imageThen, add statements to display a list of all directories where the Python interpreter looks for module files
print( ‘Python Module Search Path: ‘ )

for dir in sys.path :

print( dir )

imageFinally, add statements to display a list of all the Python keywords
print( ‘Python Keywords: ‘ )

for word in keyword.kwlist :

print( word )

imageSave the file in your scripts directory then open a Command Prompt window there and run this program - to see details of the Python version on your system

image

image

The first item on the Python search path is your current directory - so any file within there or within any subdirectories you make there will be found by the Python interpreter.

image

Spend a little time with the Interactive Mode help utility to discover lots more about Python.

Performing mathematics

Python includes a “math” module that provides lots of methods you can use to perform mathematical procedures once imported.

The math.ceil() and math.floor() methods enable a program to perform rounding of a floating point value specified between their parentheses to the closest integer - math.ceil() rounds up and math.floor() rounds down but the value returned, although an integer, is a float data type rather than an int data type.

image

Integers can be cast from the int data type to the float data type using the float() function and to the string data type using the str() function.

The math.pow() method requires two arguments to raise a specified value by a specified power. The math.sqrt() method, on the other hand, simply requires a single argument and returns the square root of that specified value. Both method results are returned as a numeric value of the float data type.

Typical trigonometry can be performed using methods from the math module too, such as math.sin(), math.cosin() and math.tan().

Additionally, Python includes a “random” module that can be used to produce pseudo random numbers once imported into a program.

The random.random() method produces a single floating-point number between zero and 1.0. Perhaps more interestingly, the random.sample() method produces a list of elements selected at random from a sequence. This method requires two arguments to specify the sequence to select from, and the length of the list to be produced. As the range() function returns a sequence of numbers this can be used to specify a sequence as the first argument to the random.sample() method - so it will randomly select numbers from that sequence to produce a list in which no numbers repeat.

imageStart a new Python script by importing the “math” and “random” modules to make their features available

import math , random

image

maths.py

imageNext, add statements to display two rounded values

print( ‘Rounded Up 9.5:‘ , math.ceil( 9.5 ) )

print( ‘Rounded Down 9.5:‘ , math.floor( 9.5 ) )

imageNow, add a statement to initialize a variable with an integer value
num = 4

imageAdd statements to display the square and square root of the variable value

print( num , ‘Squared:‘ , math.pow( num , 2 ) )

print( num , ‘Square Root:‘ , math.sqrt( num ) )

imageThen, add a statement to produce a random list of six unique numbers between one and 49

nums = random.sample( range( 1, 49 ) , 6 )

imageFinally, add a statement to display the random list

print( ‘Your Lucky Lotto Numbers Are:‘ , nums )

imageSave the file in your scripts directory then open a Command prompt window there and run this program - to see math results and random samples

image

image

All the math methods here return floating-point numbers of the float data type.

image

The list produced by random.sample() does not actually replace elements of the sequence but merely copies a sample, as its name says.

Calculating decimals

Python programs that attempt floating-point arithmetic can produce unexpected and inaccurate results because the floating-point numbers cannot accurately represent all decimal numbers.

imageStart a new Python script by initializing two variables with floating-point values

item = 0.70

rate = 1.05

image

inaccurate.py

imageNext, initialize two more variables by attempting floating-point arithmetic with the first two variables

tax = item * rate
total
= item + tax

imageNow, add statements to display variable values formatted to have two decimal places so trailing zeros are shown

print( ‘Item:\t’ , ‘%.2f’ % item )

print( ‘Tax:\t’ , ‘%.2f’ % tax )

print( ‘Total:\t’ , ‘%.2f’ % total )

imageSave the file in your scripts directory then open a Command Prompt window there and run the program - to see the output display an inaccurate addition

image

image

Here, the variable values are formatted using a string substitution technique to show two decimal places - described in more detail here.

imageTo help understand this problem, edit all three print statements to display the variable values expanded to twenty decimal places, then run the modified program

print( ‘Item:\t’ , ‘%.20f’ % item )

print( ‘Tax:\t’ , ‘%.20f’ % tax )

print( ‘Total:\t’ , ‘%.20f’ % total )

image

expanded.py

image

image

This problem is not unique to Python - Java has a BigDecimal class that overcomes this problem in much the same way as the decimal module in Python.

It is now clear that the tax value is represented numerically slightly below 0.735 so gets rounded down to 0.73. Conversely, the total value is represented numerically slightly above 1.435 so gets rounded up to 1.44, creating the apparent addition error.

Errors in floating-point arithmetic can be avoided using Python’s “decimal” module. This provides a Decimal() object with which floating-point numbers can be more accurately represented.

imageAdd a statement at the beginning of the program to import the “decimal” module to make all features available
from decimal import *

image

decimals.py

imageNext, edit the first two variable assignment to objects

item = Decimal( 0.70 )

rate = Decimal( 1.05 )

imageSave the changes then run the modified program to see both tax and total representations will now get rounded down - so the output will show accurate addition when string formatting is changed back to two decimal places

image

image

Always use the Decimal() object to calculate monetary values or anywhere that accuracy is essential.

Telling the time

The Python “datetime” module can be imported into a program to make use of times and dates. It provides a datetime object with attributes of year, month, day, hour, minute, second, microsecond.

A datetime object has a today() method that assigns the current date and time values to its attributes and returns them in a tuple. It also has a getattr() method that requires two arguments specifying the datetime object name and attribute to retrieve. Alternatively, the attributes can be referenced using dot notation such as datetime.year.

image

As the datetime object is in a module of the same name, simply importing the module means it would be referenced as datetime.datetime. Use from datetime import * so it can be referenced just as datetime.

All values in a datetime object are stored as numeric values but can, usefully, be transformed into text equivalents using its strftime() method. This requires a single string argument that is a “directive” specifying which part of the tuple to return and in what format. The possible directives are listed in the table below:

Directive:

Returns:

%A

Full weekday name (%a for abbreviated day name)

%B

Full month name (%b for abbreviated month name)

%c

Date and time appropriate for locale

%d

Day of the month number 1-31

%f

Microsecond number 0-999999

%H

Hour number 0-23 (24-hour clock)

%I

Hour number 1-12 (12-hour clock)

%j

Day of the year number 0-366

%m

Month number 1-12

%M

Minute number 0-59

%p

AM or PM equivalent for locale

%S

Second number 0-59

%w

Week day number 0(Sunday)-6

%W

Week of the year number 0-53

%X

Time appropriate for locale (%x for appropriate date)

%Y

Year 0001-9999 (%y for year 00-99)

%z

Timezone offset from UTC as +HHMM or -HHMM

%Z

Timezone name

image

As the strftime() method requires a string argument, the directive must be enclosed between quote marks.

imageStart a new Python script by importing the “datetime” module to make its features available
from datetime import *

image

today.py

imageNext, create a datetime object with attributes assigned to current date and time values then display its contents

today = datetime.today()

print( ‘Today Is:‘ , today )

imageAdd a loop to display each attribute value individually
for attr in \

[ ‘year’,‘month’,‘day’,‘hour’,‘minute’,’second’,’microsecond’ ] :

print( attr , ‘:\t’ , getattr( today , attr ) )

imageNow, add a statement to display time using dot notation

print( ‘ Time:‘ , today.hour , ‘:’ , today.minute , sep = ‘‘ )

imageThen, assign formatted day and month names to variables

day = today.strftime( ‘%A’ )

month = today.strftime( ‘%B’ )

imageFinally, add a statement to display the formatted date

print( ‘Date:‘ , day , month , today.day )

imageSave the file in your scripts directory then open a Command Prompt window there and run this program - to see the date and time values get displayed

image

image

Notice how the \ backslash character is used in this loop to allow a statement to continue on the next line without causing an error.

image

You can assign new values to attributes of a datetime object using its replace() method, such as today = today.replace(year=2015)

Running a timer

Getting the current time both before and after an event means that the duration of the event can be calculated by their difference. The Python “time” module can be imported into a program to provide various time-related functions.

Current system time is usually counted as the number of seconds elapsed since the Epoch at 00:00:00 GMT on January 1, 1970. The time module’s time() method returns the current time in seconds since the Epoch as a floating point number when called.

image

The gmtime() method converts elapsed time from the Epoch to a struct_time object at UTC with the Daylight Saving Time always set to zero, whereas localtime() converts to a struct_time object at your local system time.

The figure returned by the time() method can be converted into a “struct_time” object using gmtime() or localtime() methods. This object has attributes of tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_yday and tm_isdst that can be referenced using dot notation. For example,struct.tm_wday.

All values in a struct_time object are stored as numeric values but can be transformed into text equivalents using the strftime() method. This requires an argument that is a format “directive” followed by the name of the struct_time object. The possible directives include those listed in the table herefor the datetime object. For example, strftime( ‘%A’ , struct ) for weekday.

Usefully, the time module also provides a sleep() method that can be used to pause execution of a program. Its argument specifies the amount of time in seconds by which to delay execution.

imageStart a new Python script by importing the “time” module to make its features available
from time import *

image

timer.py

imageNext, initialize a variable with a floating point number that is the current elapsed time since the epoch
start_timer = time()

imageNow, add a statement to create a struct_time object from the elapsed time value
struct = localtime( start_timer )

imageThen, announce that a countdown timer is about to begin from the current time starting point

print( ‘\nStarting Countdown At:’ , strftime( ‘%X’ , struct ) )

imageAdd a loop to initialize and print a counter variable value then decrement the counter by one and pause for one second on each iteration

i = 10

while i > -1 :

print( i )
i -= 1

sleep( 1 )

image

The argument to the sleep() method may be a floating point number to indicate a more precise sleep pause time.

imageNext, initialize a variable with a floating point number that is the current elapsed time now since the Epoch
end_timer = time()

imageNow, initialize a variable with the rounded seconds value of the time difference between the two timed points
difference = round( end_timer - start_timer )

imageFinally, add a statement to display the time taken to execute the countdown loop
print( ‘\nRuntime:’ , difference , ‘Seconds’ )

imageSave the file in your scripts directory then open a Command Prompt window there and run this program - to see the loop pause on each iteration and elapsed time

image

image

Do not confuse the time.strftime() method used in this example with the datetime.strftime() method used in the previous example.

Matching patterns

The Python “re” module can be imported into a program to make use of Regular Expression patterns that describe a particular string of characters. Regular Expressions are useful for text validation and for search-and-replace operations within text by matching their specified pattern to a section of the text.

image

The topic of Regular Expressions is extensive and beyond the remit of this book - but a brief introduction is provided here for completeness.

A Regular Expression pattern may consist entirely of “literal characters” describing a character string to match within some text. For example, the Regular Expression “wind” finds a match in “windows” - the pattern literally matches the string in the text. More typically, a Regular Expresssion pattern consists of a combination of literal characters and these “metacharacters”:

Metacharacter:

Matches:

Example:

.

Any Characters

py..on

^

First Characters

^py

$

Final Characters

....on$

*

Zero Or More Repetitions

py*

+

One Or More Repetitions

py+

?

Zero Or One Repetitions

py?

{ }

Multiple Repetitions

a{ 3 }

[ ]

Character Class

[ a-z ]

\

Special Sequence

\s

|

Either Optional Character

a | b

( )

Expression Group

( ... )

image

The character class [a-z] matches only lowercase characters but [a-z0-9] also matches digits.

A combination of literals and metacharacters defining a pattern to be matched can be specified to the re.compile() method to return a pattern object. This object has a match() method to specify a string within its parentheses to compare against the pattern.

When a match() comparison succeeds, a match object is returned containing information about the match, otherwise a None value is returned when the comparison fails.

A match object has start() and end() methods, which return the position of the match, and a group() method that returns the string matched by the comparison.

imageStart a new Python script by importing the “re” module to make the regular expression methods available
from re import *

image

regex.py

imageNext, initialize a variable with a regular expression object

pattern = \ compile( ‘(^|\s)[-a-z0-9_.]+@([-a-z0-9]+\.)+[a-z]{2,6}(\s|$)’ )

imageNow, begin a function definition by requesting user input and attempt to match that with the pattern

def get_address() :

address = input( ‘Enter Your Email Address: ‘ )

is_valid = pattern.match( address )

imageThen, add indented statements to display an appropriate message describing whether the attempt succeeded

if is_valid :

print( ‘Valid Address:’ , is_valid.group() )

else :

print( ‘Invalid Address! Please Retry...\n’ )

imageFinally, add a statement to call the defined function

get_address()

imageSave the file in your scripts directory then open a Command Prompt window there and run this program - to see that only a complete email address will validate

image

image

You can discover more about Regular Expressions in the Library Reference section of the Python documentation at docs.python.org/3/library/re.html

Summary

Functions can be stored in modules that are named as the file name without the “.py” file extension

An import statement makes module functions available in a program by dot-suffixing their name after the module name

A from import statement makes module functions available in a program without the need to dot-suffix their name

The sys module has attributes that contain the Python version number, interpreter location, and path to search for modules

The keyword module has a kwlist attribute that contains a list of all current Python keywords

The math module provides methods to perform mathematical procedures such as math.ceil() and math.floor()

The random module provides a random() method that produces pseudo random numbers and a sample() method that produces a list of elements selected at random from a sequence

The decimal module provides a Decimal() object with which floating-point numbers can be accurately represented to calculate monetary values

The datetime module provides a datetime object with year, month, day, hour, minute, second, microsecond attributes that can be referenced by dot-suffixing or with the getattr() method

A datetime object has a strftime() method that can specify a directive to return a formatted part of the object

The time module provides a time() method that returns the current elapsed time in seconds since the Epoch

The gmtime() and localtime() methods return a struct_time object that has attributes containing date and time components

The re module provides a compile() method to create a Regular Expression pattern and a match() method to compare a pattern to a specified string