H13 BG Ngôn NG Python - P5 - Updated
H13 BG Ngôn NG Python - P5 - Updated
1
CHAPTER 22 Modules: The Big Picture
2
CHAPTER 22 Modules: The Big Picture
Python module:
● pack program code and data for reuse, each file is a module
● the highest-level program organization unit provides self-contained
namespaces that minimize variable name clashes
a.py
var_1= 10
b.py
var_1=10
import a
print(a.var_1)
3
CHAPTER 22 Python Program Architecture
A Python program consists of:
● 1 main top-level file
○ contains the main flow of control of your program (e.g., main function)
● n module files (n >= 0):
○ components used by the top-level file or other modules.
4
CHAPTER 22 Python Program Architecture
Imports and Attributes
# File b.py
def spam(text):
print(text, 'spam')
# File a.py
import b
main():
b.spam('gumby')
5
CHAPTER 22 Python Program Architecture
Standard Library Modules
● Python comes with a large collection of utility modules known as the standard
library
● Link: www.python.org
6
CHAPTER 22 Python Program Architecture
How Imports Work:
They are runtime operations that perform three steps the first time a program
imports a given file:
1. Find the module’s file. # (b.*: b.py b.pyc )
2. Compile it to byte code (if needed). #(b.py -> b.pyc; b.pyc: code b.py, version
python; b.pyc)
a. Compile: If the byte code file is older than the source file (i.e., if you’ve changed the source) or
was created by a different Python version
b. Don’t compile
3. Run the module’s code to build the objects it defines.
7
CHAPTER 22 Python Program Architecture
The Module Search Path
1. The home directory of the program: automatic, searched first, its files will
override modules of the same name in other directories;
2. PYTHONPATH directories (if set): configurable
a. used to extend the path to include user-defined and platform-specific source code directories,
b. import a file that is stored in a different directory from the file that imports it
3. Standard library directories: automatic.
4. The contents of any *.pth files (if present): configurable,
a. used to extend the path to include user-defined directories, e.g., myconfig.pth in Python install
directory (C:\Python33, C:\Python33\Lib\site-packages, etc.)
5. The site-packages home of third-party extensions: automatic
8
CHAPTER 22 Python Program Architecture
The Module Search Path - Configuring the Search Path (e.g., Windows)
● PYTHONPATH:
c:\pycode\utilities;d:\pycode\package1
● C:\Python33\pydirs.pth
or C:\Python33\Lib\site-packages\pydirs.pth:
c:\pycode\utilities
d:\pycode\package1
9
CHAPTER 22 Python Program Architecture
Check sys.path
● Verify the search path settings
>>> import sys
>>> sys.path
● Modify the path only for current run
>>> sys.path.insert(0,'/path/to/mod_directory')
● PYTHONPATH and .pth files offer more permanent ways to modify the path
10
CHAPTER 23 Module Coding Basics
11
CHAPTER 23 Module Coding Basics
● Module names become variable names in a program => should follow the normal variable
name rules
○ E.g.,
# if.py
X = 10
print(“if.py”)
# test.py
import if
print(if.X)
if true:
….
● Extension modules:
○ module by writing code in an external language such as C, C++, and others
○ like normal modules: accessed with import statements, and their functions and objects as module attributes.
12
CHAPTER 23 Module Coding Basics
Module Usage
● The import Statement
>>> import module1 # Get module as a whole (one or more)
>>> module1.printer('Hello world!') # Qualify to get names
Hello world!
13
CHAPTER 23 Module Coding Basics
Imports Happen Only Once
● By default Python imports just once per file, per process.
● For example:
# simple.py
print('hello')
spam = 1 # Initialize variable
# python
>>> import simple # First import: loads and runs file's code hello
>>> simple.spam # Assignment makes an attribute
1
15
CHAPTER 23 Module Coding Basics
import and from Are Assignments - # small.py:
Cross-file name changes x = 1 # immutable (bat bien)
y = [1, 2] # mutable
● Copy two names out
● Changes my x only % python
>>> from small import x, y
● Get module name >>> x = 42
● Changes x in other module
>>> import small
>>> small.x = 42
16
CHAPTER 23 Module Coding Basics
import and from Equivalence
● Copy these two names out (only) from module import name1, name2
17
CHAPTER 23 # M.py
def func():
Module Coding Basics ...do something...
# N.py
Potential Pitfalls of the from Statement def func():
...do something else…
This overwrites the one we fetched from M # O.py
Calls N.func only! from M import func
Solutions from N import func
func() # N.func()
# O.py
import M, N
M.func()
N.func()
# O.py
from M import func as mfunc
from N import func as nfunc
mfunc(); nfunc()
18
CHAPTER 23 Module Coding Basics
Module Namespaces - Files Generate Namespaces
19
CHAPTER 23 Module Coding Basics
Illustrate >>> import module2
● Top‐level assignments create starting to load...
module attributes done loading.
>>> module2.sys
% module2.py
<module 'sys' (built-in)>
print('starting to load...')
import sys >>> module2.name
name = 42 42
def func(): >>> module2.func
pass <function func at
class klass: 0x000000000222E7B8>
pass >>> module2.klass
print('done loading.') <class 'module2.klass'>
20
CHAPTER 23 Module Coding Basics
Namespace Dictionaries: __dict__ >>> list(module2.__dict__.keys())
● Module namespaces are stored ['__loader__', 'func', 'klass',
as dictionary objects '__builtins__', '__doc__',
● access via the module’s '__file__', '__name__', 'name',
__dict__ attribute '__package__', 'sys',
'__initializing__', '__cached__']
>>> dir(module2)
21
CHAPTER 23 Module Coding Basics
Imports Versus Scopes % moda.py
● Module code can never see X = 88
def f():
names in other modules, global X
unless they are explicitly X = 99
imported.
% modb.py
X = 11
import moda
moda.f()
print(X, moda.X)
22
CHAPTER 23 Module Coding Basics
Namespace Nesting % mod1.py
X= 1
% mod3.py import mod2
X= 3 print(X, end=' ')
print(mod2.X, end=' ')
% mod2.py print(mod2.mod3.X)
X= 2
import mod3 >>> python mod1.py
print(X, end=' ')
print(mod3.X)
23
CHAPTER 23 Module Coding Basics
Reloading Modules - reload Basics import module
● reload is a function in Python ...change module.attributes
● reload is passed an existing module ...
object, not a new name. from imp import reload
● reload lives in a module in Python 3.X reload(module)
and must be imported itself. ...use module.attributes
○ Initial import …
○ Now, go change the module file …
○ Get reload itself (in 3.X)
○ Get updated exports
24
CHAPTER 23 Module Coding Basics
Reloading Modules - reload basic
● Reload runs a module file’s new code in the module’s current namespace.
● Top‐level assignments in the file replace names with new values.
● Reloads impact all clients that use import to fetch modules.
● Reloads impact future from clients only.
● Reloads apply to a single module only
25
CHAPTER 23 Module Coding Basics
% changer.py … back to the Python
message = "First version" interpreter …
def printer():
print(message)
>>> import changer
% python >>> changer.printer()
>>> import changer First version
>>> changer.printer()
First version >>> from imp import reload
>>> reload(changer)
...modify changer.py without stopping
<module 'changer' from
Python...
% changer.py as below:
'.\\changer.py'>
message = "After editing"
def printer(): >>> changer.printer()
print('reloaded:', message) reloaded: After editing
26
CHAPTER 24 Module Packages
27
Package Import Basics
● Imports are known as package imports
● The “dotted” path in the import statement is a relative path to the file mod.py
E.g.,
import dir1.dir2.mod
28
Package __init__.py Files
● Each directory named within the path of a package import statement must
contain a file named __init__.py
E.g.,
import dir1.dir2.mod
30
Package Import Example
# dir1\__init__.py # First imports run init files
print('dir1 init') >>> import dir1.dir2.mod
x= 1 dir1 init
dir2 init
# dir1\dir2\__init__.py in mod.py
print('dir2 init')
y= 2 # Later imports do not run init
>>> import dir1.dir2.mod
# dir1\dir2\mod.py …
print('in mod.py')
z= 3
31
Package Import Example
An imported directory may be passed to >>> from imp import reload
reload to force re-execution of that
single item. >>> reload(dir1)
dir1 init
<module 'dir1' from
'.\\dir1\\__init__.py'>
>>> reload(dir1.dir2)
dir2 init
<module 'dir1.dir2' from
'.\\dir1\\dir2\\__init__.py'
32
Package Import Example
from Versus import with Packages >>> from dir1.dir2 import mod
dir1 init
dir2 init
● the from statement with in mod.py
>>> mod.z
packages avoids retyping the
3
paths at each access.
>>> from dir1.dir2.mod import z
>>> z
3
34
Why Use Package Imports?
system1\ root\
utilities.py system1\
main.py __init__.py
other.py utilities.py
main.py
other.py
system2\
system2\
utilities.py __init__.py
main.py utilities.py
other.py main.py
other.py
# myfile.py
import utilities system3\
utilities.function('spam') __init__.py
myfile.py
35
Why Use Package Imports?
root\ # myfile.py
system1\ import system1.utilities
__init__.py
utilities.py import system2.utilities
main.py system1.utilities.function('spam')
other.py system2.utilities.function('eggs')
system2\
__init__.py
utilities.py
main.py
other.py
system3\
__init__.py
myfile.py
36
Package Relative Imports
● Imports with dots: search for mypkg\
modules inside the package __init__.py
directory only main.py
● Imports without dots: look string.py
elsewhere on the sys.path
search path
from . import string
import string
37
Package Relative Imports
Code located in some module A.B.C can use any of these forms:
A/B/C test.py
38
Package Relative Imports
The Scope of Relative Imports:
● Relative imports apply to imports within packages only.
● Relative imports apply to the from statement only.
39
Package Relative Imports
Relative Imports in Action # C:\code>
● imports outside packages: >>> import string
>>> string
normal imports are still relative <module 'string' from
to the “home” directory 'C:\\Python33\\lib\\string.py'>
● package relative import syntax
# C:/code/string.py
is not even allowed in code that print('string' * 5)
is not in a file:
>>> import string
stringstringstringstringstring
>>> string
<module 'string' from '.\\string.py'>
# C:\code\string.py
print('string' * 8)
# C:\code\pkg\spam.py
import eggs
print(eggs.X)
# C:\code\pkg\eggs.py
X = 99999
import string
print(string)
# C:\code>
>>> import pkg.spam
41
Package Relative Imports
Relative Imports in Action
# code\string.py
print('string' * 8)
# code\pkg\spam.py
from . import eggs
print(eggs.X)
# code\pkg\eggs.py
X = 99999
import string
print(string)
# C:\code>
>>> import pkg.spam
42
Package Relative Imports
Relative Imports in Action
# code\string.py
print('string' * 8)
# code\pkg\spam.py
from . import eggs
print(eggs.X)
# code\pkg\eggs.py
X = 99999
from . import string
print(string)
# C:\code>
>>> import pkg.spam
43
Package Relative Imports
Namespace Packages:
● Known as the virtual concatenation of individual directory components,
● Allows nested parts to be accessed through its name with normal imports
44
Package Relative Imports >>> sub.__path__
_NamespacePath(['C:\\code\\ns\\dir1\\
# C:\code\ns\dir1\sub\mod1.py sub', 'C:\\code\\ns\\dir2\\sub'])
print(r'dir1\sub\mod1')
>>> from sub import mod1
# C:\code\ns\dir2\sub\mod2.py dir1\sub\mod1
print(r'dir2\sub\mod2')
>>> import sub.mod2
set PYTHONPATH=C:\code\ns\dir1; dir2\sub\mod2
C:\code\ns\dir2
>>> mod1
>>> import sub <module 'sub.mod1' from
>>> sub 'C:\\code\\ns\\dir1\\sub\\mod1.py'>
<module 'sub' (namespace)>
>>> sub.mod2
<module 'sub.mod2' from
'C:\\code\\ns\\dir2\\sub\\mod2.py'>
45
Package Relative Imports
Namespace Package Nesting # ns\dir2\sub\lower\mod3.py
print(r'dir2\sub\lower\mod3')
47
Module Design Concepts
● You’re always in a module in Python.
● Minimize module coupling: global variables.
● Maximize module cohesion: unified purpose.
● Modules should rarely change other
modules’ variables.
49
Data Hiding in Modules # alls.py
__all__ = ['a', '_c']
a, b, _c, _d = 1, 2, 3, 4
● Minimizing from * Damage: _X
and __all__ >>> from alls import *
○ __all__ identifies names to be >>> a, _c
copied with a from * statement. (1, 3)
>>> b
NameError: name 'b' is not defined
51
Unit Tests with __name__
# minmax.py
print('I am:', __name__)
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
# test_minmax.py
import minmax
print("test minmax")
52
Unit Tests with __name__
#minmax2.py
print('I am:', __name__)
if __name__ == '__main__':
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
# test_minmax.py
import minmax
print("test minmax")
53
The as Extension for import and from
import reallylongmodulename as name
name.func()
54
Importing Modules by Name String
● The program get the name of a >>> import 'string'
module as a string at runtime File "<stdin>", line 1 import
(e.g. from a user selection in a "string"
GUI, or a parse of an XML
document, for instance) # Run a string of code
○ Running Code Strings: exec, it >>> modname = 'string'
must compile the import statement
>>> exec('import ' + modname)
each time it runs, slowly
>>> string
<module 'string' from …>
55
Importing Modules by Name String
● The program get the name of a >>> import 'string'
module as a string at runtime (e.g. File "<stdin>", line 1 import "string"
from a user selection in a GUI, or a
parse of an XML document) >>> modname = 'string'
○ Running Code Strings (exec) >>> string = __import__(modname)
○ Direct Calls: Two Options >>> string
■ __import__
■ importlib.import_module(...) >>> import importlib
>>> modname = 'string'
>>> string =
importlib.import_module(modname)
>>> string
56
Module Gotchas
● Statement Order Matters in Top-Level Code func1()
○ Code at the top level of a module file (not nested in a
function) runs when Python reaches it during an import def func1():
=> cannot reference names assigned lower in the file print(func2())
○ Code inside a function body doesn’t run until the
function is called => reference names anywhere in the
file func1()
def func2():
return "Hello"
func1()
57
Module Gotchas
● from Copies Names but Doesn’t Link # nested3.py
import nested1
# nested1.py
nested1.X = 88
X = 99
def printer(): nested1.printer()
print(X)
% python nested3.py
# nested2.py 88
from nested1 import X, printer
X = 88
printer()
% python nested2.py
99
58
Module Gotchas
● reload May Not Impact from Imports
from module import X
# before reload
# module.py from imp import reload
X = 10 reload(module)
print(X)
import module
# after reload print(X)
# module.py print(module.X)
X = 12
print(X)
59
Module Gotchas
● from * Can Obscure the Meaning of Variables
60