\[ [Index](index.md) | [Exercise 8.6](ex8_6.md) | [Exercise 9.2](ex9_2.md) \] # Exercise 9.1 *Objectives:* - A review of module basics This exercise is about some of the more tricky details of library modules. Start this exercise by creating a very simple library module: ```python # simplemod.py x = 42 # A global variable # A simple function def foo(): print('x is', x) # A simple class class Spam: def yow(self): print('Yow!') # A scripting statement print('Loaded simplemod') ``` ## (a) Module Loading and System Path Try importing the module you just created: ```python >>> import simplemod Loaded simplemod >>> simplemod.foo() x is 42 >>> ``` If this failed with an `ImportError`, your path setting is flaky. Look at the value of `sys.path` and fix it. ```python >>> import sys >>> sys.path ... look at the result ... >>> ``` ## (b) Repeated Module Loading Make sure you understand that modules are only loaded once. Try a repeated import and notice how you do not see the output from the `print` function: ```python >>> import simplemod >>> ``` Try changing the value of `x` and see that a repeated import has no effect. ```python >>> simplemod.x 42 >>> simplemod.x = 13 >>> simplemod.x 13 >>> import simplemod >>> simplemod.x 13 >>> ``` Use `importlib.reload()` if you want to force a module to reload. ```python >>> import importlib >>> importlib.reload(simplemod) Loaded simplemod >>> simplemod.x 42 >>> ``` `sys.modules` is a dictionary of all loaded modules. Take a look at it, delete your module, and try a repeated import. ```python >>> sys.modules ... look at output ... >>> sys.modules['simplemod'] >>> del sys.modules['simplemod'] >>> import simplemod Loaded simplemod >>> ``` ## (c) from module import Restart Python and import a selected symbol from a module. ```python >>> ############### [ RESTART ] ############### >>> from simplemod import foo Loaded simplemod >>> foo() x is 42 >>> ``` Notice how this loaded the entire module (observe the output of the print function and how the `x` variable is used). When you use `from`, the module object itself is not visible. For example: ```python >>> simplemod.foo() Traceback (most recent call last): File "", line 1, in NameError: name 'simplemod' is not defined >>> ``` Make sure you understand that when you export things from a module, they are simply name references. For example, try this and explain: ```python >>> from simplemod import x,foo >>> x 42 >>> foo() x is 42 >>> x = 13 >>> foo() x is 42 # !! Please explain >>> x 13 >>> ``` ## (d) Broken reload() Create an instance: ```python >>> import simplemod >>> s = simplemod.Spam() >>> s.yow() Yow! >>> ``` Now, go to the `simplemod.py` file and change the implementation of `Spam.yow()` to the following: ```python # simplemod.py ... class Spam: def yow(self): print('More Yow!') ``` Now, watch what happens on a reload. Do not restart Python for this part. ```python >>> importlib.reload(simplemod) Loaded simplemod >>> s.yow() 'Yow!' >>> t = simplemod.Spam() >>> t.yow() 'More Yow!' >>> ``` Notice how you have two instances of `Spam`, but they're using different implementations of the `yow()` method. Yes, actually both versions of code are loaded at the same time. You'll find other oddities as well. For example: ```python >>> s >>> isinstance(s, simplemod.Spam) False >>> isinstance(t, simplemod.Spam) True >>> ``` Bottom line: It's probably best not to rely on reloading for anything important. It might be fine if you're just trying to debug some things (as long as you're aware of its limitations and dangers). \[ [Solution](soln9_1.md) | [Index](index.md) | [Exercise 8.6](ex8_6.md) | [Exercise 9.2](ex9_2.md) \] ---- `>>>` Advanced Python Mastery `...` A course by [dabeaz](https://www.dabeaz.com) `...` Copyright 2007-2023 ![](https://i.creativecommons.org/l/by-sa/4.0/88x31.png). This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)