Skip to content

Latest commit

 

History

History
211 lines (166 loc) · 4.19 KB

ex9_1.md

File metadata and controls

211 lines (166 loc) · 4.19 KB

[ Index | Exercise 8.6 | Exercise 9.2 ]

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:

# 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:

>>> 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.

>>> 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:

>>> import simplemod
>>>

Try changing the value of x and see that a repeated import has no effect.

>>> 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.

>>> import importlib
>>> importlib.reload(simplemod)
Loaded simplemod
<module 'simplemod' from 'simplemod.py'>
>>> 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.

>>> sys.modules
... look at output ...
>>> sys.modules['simplemod']
<module 'simplemod' from 'simplemod.py'>
>>> del sys.modules['simplemod']
>>> import simplemod
Loaded simplemod
>>>

(c) from module import

Restart Python and import a selected symbol from a module.

>>> ############### [ 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:

>>> simplemod.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
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:

>>> 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:

>>> 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:

# simplemod.py
...

class Spam:
    def yow(self):
        print('More Yow!')

Now, watch what happens on a reload. Do not restart Python for this part.

>>> importlib.reload(simplemod)
Loaded simplemod
<module 'simplemod' from 'simplemod.py'>
>>> 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:

>>> s
<simplemod.Spam object at 0x1006940b8>
>>> 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 | Index | Exercise 8.6 | Exercise 9.2 ]


>>> Advanced Python Mastery
... A course by dabeaz
... Copyright 2007-2023

. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License