Defining Your Own Modules

Writing and Running a Program, explained that in order to save code for later use, you can put it in a file with a .py extension, and it demonstrated how to run that code. Chapter 3, Designing and Using Functions, also included this function definition:

 >>>​​ ​​def​​ ​​convert_to_celsius(fahrenheit:​​ ​​float)​​ ​​->​​ ​​float:
 ...​​ ​​"""Return the number of Celsius degrees equivalent to fahrenheit
 ... degrees.
 ...
 ... >>> convert_to_celsius(75)
 ... 23.88888888888889
 ... """
 ...​​ ​​return​​ ​​(fahrenheit​​ ​​-​​ ​​32.0)​​ ​​*​​ ​​5.0​​ ​​/​​ ​​9.0
 ...

Put the function definition for convert_to_celsius from Defining Our Own Functions, in a file called temperature.py. (You can save this file anywhere you like, although most programmers create a separate directory for each set of related files that they write.) Add another function to temperature.py called above_freezing that returns True if and only if its parameter celsius is above freezing as shown in the screenshot.

images/modules/temperature.png

Congratulations—you have created a module called temperature. Now that you’ve created this file, you can run it and import it like any other module:

 >>>​​ ​​import​​ ​​temperature
 >>>​​ ​​celsius​​ ​​=​​ ​​temperature.convert_to_celsius(33.3)
 >>>​​ ​​temperature.above_freezing(celsius)
 True

What Happens During Import

Let’s try another experiment. Create a file called experiment.py with this one statement inside it:

 print​(​"The panda's scientific name is 'Ailuropoda melanoleuca'"​)

Run experiment.py and then import it:

 >>>​​ ​​import​​ ​​experiment
 The panda's scientific name is 'Ailuropoda melanoleuca'

What this shows is that Python executes modules as it imports them. You can do anything in a module you would do in any other program, because as far as Python is concerned, it’s just another bunch of statements to be run.

Let’s try another experiment. Start a fresh Python session, run experiment.py, and try importing module experiment twice in a row:

 >>>​​ ​​import​​ ​​experiment
 The panda's scientific name is 'Ailuropoda melanoleuca'
 >>>​​ ​​import​​ ​​experiment
 >>>

Notice that the message wasn’t printed the second time. That’s because Python loads modules only the first time they’re imported. Internally, Python keeps track of the modules it has already seen; when it is asked to load one that’s already in that list, it just skips over it. This saves time and will be particularly important when you start writing modules that import other modules, which in turn import other modules—if Python didn’t keep track of what was already in memory, it could wind up loading commonly used modules like math dozens of times.

Even if you import a module, edit that module’s file, and then reimport, the module won’t be reloaded. Your edits won’t have any effect until you restart the shell or call imp.reload. For example, after we’ve imported experiment, we’ll change the file contents to this:

 print​(​"The koala's scientific name is 'Phascolarctos cinereus'"​)

We’ll now call imp.reload to reload module experiment:

 >>>​​ ​​import​​ ​​experiment
 The panda's scientific name is 'Ailuropoda melanoleuca'
 >>>​​ ​​import​​ ​​experiment
 >>>​​ ​​import​​ ​​imp
 >>>​​ ​​imp.reload(experiment)
 The koala's scientific name is 'Phascolarctos cinereus'
 <module 'experiment' from '/Users/campbell/Documents/experiment.py'>

In this example, the call on imp.reload returns the module that was imported.

Selecting Which Code Gets Run on Import: __main__

As we saw in Writing and Running a Program, every Python module can be run directly (from the command line or by running it from an IDE like IDLE), or, as we saw earlier in this section, it can be run indirectly (imported by another program). If a module is to be imported by another module, then the files containing the two modules should be saved in the same directory (an alternative approach would be to use absolute file paths, which are explained in Opening a File).

Sometimes we want to write code that should only be run when the module is run directly and not when the module is imported. Python defines a special string variable called __name__ in every module to help us figure this out. Suppose we put the following into echo.py:

 print​(​"__name__ is"​, __name__)

If we run this file, its output is as follows:

 __name__ is __main__

As promised, Python has created variable __name__. Its value is "__main__", meaning this module is the main program. But look at what happens when we import echo (instead of running it directly):

 >>>​​ ​​import​​ ​​echo
 __name__ is echo

The same thing happens if we write a program that does nothing but import our echoing module. Create a file import_echo.py with this code inside it:

 import​ echo
 
 print​(​"After import, __name__ is"​, __name__,
 "and echo.__name__ is"​, echo.__name__)

When run from the command line, the code produces this:

 __name__ is echo
 After import, __name__ is __main__ and echo.__name__ is echo

When Python imports a module, it sets that module’s __name__ variable to be the name of the module rather than the special string "__main__". This means that a module can tell whether it is the main program. Now create a file named main_example.py with this code inside it:

 if​ __name__ == ​"__main__"​:
 print​(​"I am the main program."​)
 else​:
 print​(​"Another module is importing me."​)

Try it. See what happens when you run main_example.py directly and when you import it.

Some of our modules contain not only function definitions but also programs. For example, create a new module temperature_program that contains the functions from temperature and a little program:

images/modules/temperature_program.png

When that module is run, it prompts the user to enter a value and, depending on the value entered, prints one of two messages:

images/modules/temperature_program_output.png

Let’s create another module, baking.py, that uses the conversion function from module temperature_program as shown in the top screenshot.

images/modules/baking.png

When baking.py is run, it imports temperature_program, so the program at the bottom of temperature_program.py is executed:

images/modules/baking_output.png

Since we don’t care whether a temperature is above freezing when preheating our oven, when importing temperature_program.py we can prevent that part of the code from executing by putting it in an if __name__ == ’__main__’: block as shown in the top screenshot.

images/modules/temperature_program_main.png

Now when baking.py is run, only the code from temperature_program that is outside of the if __name__ == ’__main__’: block is executed as shown in the second screenshot.

images/modules/baking_output_2.png

We will see other uses of __name__ in the following sections and in later chapters.