本节介绍模块的概念以及如何使用跨多个文件的函数。
模块和导入任何一个 Python 源文件都是一个模块。
# foo.py def grok(a): ... def spam(b): ...import 语句加载并执行一个模块。
# program.py import foo a = foo.grok(2) b = foo.spam('Hello') ... 命名空间模块是命名值的集合,有时也称为命名空间。名称是源文件中定义的所有全局变量和函数。导入之后,模块名称用作前缀。因此,称为命名空间。
import foo a = foo.grok(2) b = foo.spam('Hello') ...模块名直接绑定到文件名(foo -> foo.py)。
全局定义填充模块命名空间的内容是定义在全局(global)作用域中任何内容。考虑定义了相同变量 x 的两个模块。
# foo.py x = 42 def grok(a): ... # bar.py x = 37 def spam(a): ...在本例中,x 指向不同的变量。一个是 foo.x,另一个是 bar.x。不同的模块可以使用相同的名称并且这些名称不会相互冲突。
模块是隔离的。
把模块当做环境对于所有定义在模块里面的代码而言,模块构成一个封闭的环境。
# foo.py x = 42 def grok(a): print(x)全局变量始终绑定到封闭模块(相同文件),每个源文件都是它自己的小宇宙。
模块执行导入模块时,模块中的所有语句依次执行(execute),直到到达文件末尾。模块命名空间的内容是所有的全局名称,这些名称在执行过程结束时仍然被定义。如果有脚本语句在全局作用域中执行任务(如打印,创建文件等),您将看到它们在导入模块时运行。
import as 语句可以在导入模块时更改其名称:
import math as m def rectangular(r, theta): x = r * m.cos(theta) y = r * m.sin(theta) return x, y它的作用与普通导入相同,仅仅是重命名模块而已。
from import语句from import语句从模块中选出符号并使它们在局部可访问。
from math import sin, cos def rectangular(r, theta): x = r * cos(theta) y = r * sin(theta) return x, y这允许使用模块的某些部分,而不必输入模块前缀。对于经常使用的名称,这非常有用。
导入说明有关导入的各种变化不改变模块的工作方式。
import math # vs import math as m # vs from math import cos, sin ...具体来说,import 始终执行整个文件并且模块仍然是隔离的环境。
import module as 语句只局部地更改名称。在后台,from math import cos, sin 语句仍加载全部的数学模块。当导入完成后,它仅仅将模块中的 cos 和 sin 名称复制到局部命名空间中。
模块加载每个模块仅加载和执行一次。注意:重复导入仅返回先前所加载模块的引用
sys.modules 是所有已加载模块的字典。
>>> import sys >>> sys.modules.keys() ['copy_reg', '__main__', 'site', '__builtin__', 'encodings', 'encodings.encodings', 'posixpath', ...] >>>注意:当修改模块的源代码后,如果重复import语句会产生一个常见的困惑。由于模块缓存 sys.modules,重复导入总是返回之前加载的模块——即使更改已经发生。将修改后的代码加载到 Python 中最安全的方式是退出然后重启解释器。
定位模块搜索模块时,Python 从路径列表(sys.path)中查询。
>>> import sys >>> sys.path [ '', '/usr/local/lib/python36/python36.zip', '/usr/local/lib/python36', ... ]当前工作目录通常是第一个。
模块搜索路径如前所述,sys.path 包含搜索路径。可以根据需要手动调整 。
import sys sys.path.append('/project/foo/pyfiles')也可以通过环境变量添加搜索路径。
% env PYTHONPATH=http://www.likecs.com/project/foo/pyfiles python3 Python 3.6.0 (default, Feb 3 2017, 05:53:21) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] >>> import sys >>> sys.path ['','/project/foo/pyfiles', ...]在大部分情况下,没必要手动调整模块搜索路径。但是,如果尝试导入的 Python 代码位于特殊位置,或者无法从当前工作目录轻松访问,那么就需要手动调整搜索路径了。
练习因为本练习涉及模块,所以确保在适当的环境中运行 Python 至关重要。模块经常给编程新手带来问题,这些问题与当前工作目录相关或者与 Python 路径设置相关。对于本课程,假定您是在 Work/ 目录下编写所有的代码。为了获得最佳结果,应该确保也是在 Work/ 目录下运行解释器。否则,需要确保 practical-python/Work 已添加到 sys.path。
练习 3.11:模块导入在第 3 节中,我们创建了一个通用目标函数 parse_csv() 用于解析 CSV 数据文件的内容。
现在,我们来看看如何在其它程序中使用该函数。首先,启动一个新的 shell 窗口,进入到放置所有文件的目录中。我们将要导入它们。
启动 Python 交互模式。
bash % python3 Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>