As we’ve seen, a module’s code is run only once per process by default. To force a module’s code to be reloaded and rerun, you need to ask Python to do so explicitly by calling the reload built-in function. In this section, we’ll explore how to use reloads to make your systems more dynamic. In a nutshell:
Imports (via both import and from statements) load and run a module’s code only the first time the module is imported in a process.
Later imports use the already loaded module object without reloading or rerunning the file’s code.
The reload function forces an already loaded module’s code to be reloaded and rerun. Assignments in the file’s new code change the existing module object in place.
Why care about reloading modules? In short, dynamic customization: the reload function allows parts of a program to be changed without stopping the whole program. With reload, the effects of changes in components can be observed immediately. Reloading doesn’t help in every situation, but where it does, it makes for a much shorter development cycle. For instance, imagine a database program that must connect to a server on startup; because program changes or customizations can be tested immediately after reloads, you need to connect only once while debugging. Long-running servers can update themselves this way, too.
Because Python is interpreted (more or less), it already gets rid of the compile/link steps you need to go through to get a C program to run: modules are loaded dynamically when imported by a running program. Reloading offers a further performance advantage by allowing you to also change parts of running programs without stopping.
Though beyond this book’s scope, note that reload currently only works on modules written in Python; compiled extension modules coded in a language such as C can be dynamically loaded at runtime, too, but they can’t be reloaded (though most users probably prefer to code customizations in Python anyhow!).
Version skew note: In Python 2.X, reload is available as a built-in function. In Python 3.X, it has been moved to the imp standard library module—it’s known as imp.reload in 3.X. This simply means that an extra import or from statement is required to load this tool in 3.X only. Readers using 2.X can ignore these imports in this book’s examples, or use them anyhow—2.X also has a reload in its imp module to ease migration to 3.X. Reloading works the same regardless of its packaging.
Unlike import and from:
reload is a function in Python, not a statement.
reload is passed an existing module object, not a new name.
reload lives in a module in Python 3.X and must be imported itself.
Because reload expects an object, a module must have been previously imported successfully before you can reload it (if the import was unsuccessful due to a syntax or other error, you may need to repeat it before you can reload the module). Furthermore, the syntax of import statements and reload calls differs: as a function reloads require parentheses, but import statements do not. Abstractly, reloading looks like this:
import module # Initial import ...use module.attributes... ... # Now, go change the module file ... from imp import reload # Get reload itself (in 3.X) reload(module) # Get updated exports ...use module.attributes...
The typical usage pattern is that you import a module, then change its source code in a text editor, and then reload it. This can occur when working interactively, but also in larger programs that reload periodically.
When you call reload, Python rereads the module file’s source code and reruns its top-level statements. Perhaps the most important thing to know about reload is that it changes a module object in place; it does not delete and re-create the module object. Because of that, every reference to an entire module object anywhere in your program is automatically affected by a reload. Here are the details:
reload runs a module file’s new code in the module’s current namespace. Rerunning a module file’s code overwrites its existing namespace, rather than deleting and re-creating it.
Top-level assignments in the file replace names with new values. For instance, rerunning a def statement replaces the prior version of the function in the module’s namespace by reassigning the function name.
Reloads impact all clients that use import to fetch modules. Because clients that use import qualify to fetch attributes, they’ll find new values in the module object after a reload.
Reloads impact future from clients only. Clients that used from to fetch attributes in the past won’t be affected by a reload; they’ll still have references to the old objects fetched before the reload.
Reloads apply to a single module only. You must run them on each module you wish to update, unless you use code or tools that apply reloads transitively.
To demonstrate, here’s a more concrete example of reload in action. In the following, we’ll change and reload a module file without stopping the interactive Python session. Reloads are used in many other scenarios, too (see the sidebar Why You Will Care: Module Reloads), but we’ll keep things simple for illustration here. First, in the text editor of your choice, write a module file named changer.py with the following contents:
message = "First version"
def printer():
print(message)
This module creates and exports two names—one bound to a string, and another to a function. Now, start the Python interpreter, import the module, and call the function it exports. The function will print the value of the global message variable:
%python>>>import changer>>>changer.printer()First version
Keeping the interpreter active, now edit the module file in another window:
...modify changer.py without stopping Python...%notepad changer.py
Change the global message variable, as well as the printer function body:
message = "After editing"
def printer():
print('reloaded:', message)
Then, return to the Python window and reload the module to fetch the new code. Notice in the following interaction that importing the module again has no effect; we get the original message, even though the file’s been changed. We have to call reload in order to get the new version:
...back to the Python interpreter...>>>import changer>>>changer.printer()# No effect: uses loaded module First version >>>from imp import reload>>>reload(changer)# Forces new code to load/run <module 'changer' from '.\\changer.py'> >>>changer.printer()# Runs the new version now reloaded: After editing
Notice that reload actually returns the module object for us—its result is usually ignored, but because expression results are printed at the interactive prompt, Python shows a default <module 'name'...> representation.
Two final notes here: first, if you use reload, you’ll probably want to pair it with import instead of from, as the latter isn’t updated by reload operations—leaving your names in a state that’s strange enough to warrant postponing further elaboration until this part’s “gotchas” at the end of Chapter 25. Second, reload by itself updates only a single module, but it’s straightforward to code a function that applies it transitively to related modules—an extension we’ll save for a case study near the end of Chapter 25.