- 为了编写可维护的代码,我们把函数分组,分别放到不同的文件夹里,在python中,一个.py文件就称之为一个模块(Module)
- 使用模块有什么好处呢:一是:大大提高了代码的可维护性,当一个模块编写完成以后,就可以在其他地方引用这些模块;二是:使用模块避免函数名和变量名冲突,相同名字的函数和变量可以存在不同的模块中,但也要注意,不要与内置函数名冲突;
- 为了避免不同的人编写的模块名相同,python又引入了按目录来组织模块的方法,成为包(Package);
- 举个例子,一个
abc.py
的文件就是一个名字叫abc
的模块,一个xyz.py
的文件就是一个名字叫xyz
的模块,现在假设我们的这两个模块的名字与其他模块冲突了,我们可以通过包来组织模块,方法就是选择一个顶层包名,比如mycompany
,按照如下目录存放:
- 引入了包以后,只要顶层的包名不与其他人冲突,把所有模块就不会与其他人冲突,现在
abc.py
模块的名字就变成了mycompany.abc
,类似的,xyz.py
的模块名变成了mycompany.xyz
;请注意,每一个包目录下面都有一个__int__.py
的文件,这个文件时必须存在的,否则python就会这个目录变成一个普通的目录,而不是一个包,__int__.py
可以是一个空文件,也可以有代码,因为,__int__.py
本身就是一个模块,而他的模块名就是mycompany
; - 类似的可以有多级目录,组成多层级的包结构:
- 文件
www.py
模块名就是mycompany.web.www
,两个文件utils.py
的模块名分别是mycompany.utils
和mycompany.web.utils
; - mycompany.web也是一个模块,该模块对应的是
__int__.py
文件; - 自己创建模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了
sys
模块,自己的模块就不可命名为sys.py
,否则将无法导入系统自带的sys
模块。
1. 使用模块
1.1 使用模块
- python内置了很多有用的模块,安装完毕即可使用,下面以内建的
sys
模块为例,编写一个hello
的模块:
#!/user/bin/env python3 本行注释可以让此`hello.py`文件直接在linux/mac/unix上运行
# -*- coding: utf-8 -*- 本行注释表示.py文件使用标准UTF-8编码
' a test module ' # 任何代码模块的第一个字符串都被视为模块的文档注释
__author__ = 'Michael Zhao' # 使用__author__变量把作者写进去,当你公开源码的时候,别人就能看见你的名字
# 以上为python模块的标准文件模板,后面是真正代码部分
import sys # 导入sys模块,我们就有了变量sys指向sys模块,利用sys这个变量就可以访问sys模块的所有功能
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__ == '__main__':
test()
-
sys
模块有一个argv
变量,用list存储了命令行的所有参数,argv
至少有一个元素,因为第一个参数永远是该.py文件的名称,如:运行python3 hello.py
获得的sys.argv
就是['hello.py']
;运行python3 hello.py Micheal
获得的sys.argv
就是['hello.py', 'Michael']
。 -
最后注意到最后两行代码:当我们在命令行运行
hello
模块文件时,python解释器把一个特殊变量__name__
置为__main__
,而如果在其他地方导入该hello
模块时,if
判断失败,因此,这种if
测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。 -
当我们用命令行运行
hello.py
时:
$ python hello.py
Hello, world!
$ python hello.py Michael
Hello, Michael!
- 当我们启动python交互式环境,再导入
hello
模块:
(base) E:\4_Programe\1_Python\3_Code\1_LiaoDaDa>python
Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello # 导入时,没有打印Hello, world!,因为没有执行test()函数
>>> hello.test() # 调用hello.test()时,才打印Hello, world!
Hello, world!
1.2 作用域
- 在一个模块中,会定义很多变量和函数,有些我们只是希望自己使用,并不像别人共用,所以在python中是通过
_
前缀来实现的:正常的函数和变量名时公开的,可以被直接引用,比如:abc
,x123
,PI
等; - 类似于
__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,我们自己的变量一般不要用这种变量名; - 类似于
_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,如:_abc
,__abc
等;不应该被直接引用不代表不能被直接引用,是因为从编程习惯上不应该引用private函数或变量; - private函数或变量不应该被被人引用,那他有什么用呢?请看:
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
- 我们在模块里公开
greeting()
函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()
函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,即:外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。
2. 安装第三方模块
- 在Python中,安装第三方模块是通过包管理工具pip完成的
- 在Linux/Mac中安装pip这个步骤可以跳过,若在win中,确定安装python的时候,勾选了
pip
和Add python.exe to Path
,在命令提示符窗口下尝试运行pip
,如果没有报错,则正常 - 安装第三方库Pillow的命令是:
pip install Pillow # 耐心等待下载安装即可
2.1 安装常用模块
- 安装Anaconda,内置了很多第三方库;
2.2 模块搜索路径
- 当我们试图加载一个模块时,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错;
>>> import mymodule
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'mymodule'
- 默认情况下,Python解释器会搜索当前目录,所有已安装的内置模块和第三方模块,搜索路径放在
sys
模块的path
变量中:
>>> import sys
>>> sys.path
['', 'E:\\1_Install_Total\\8_Anaconda\\python37.zip', 'E:\\1_Install_Total\\8_Anaconda\\DLLs', 'E:\\1_Install_Total\\8_Anaconda\\lib', 'E:\\1_Install_Total\\8_Anaconda', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\win32', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\win32\\lib', 'E:\\1_Install_Total\\8_Anaconda\\lib\\site-packages\\Pythonwin']
- 如果要自己添加路径,有两种方法:
- 直接修改
sys.path
,添加要搜索的目录:
>>> import sys
>>> sys.path.append('/User/michael/my_py_scripts')
# 这种方法是在运行时修改,运行结束以后失效
- 设置环境变量
PYTHONPATH
,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。