当程序简单时,将代码写进一个文件即可。但当项目的复杂度增加时,会出现代码过多导致文件过大的问题。因此,模块和包就能方便管理和维护代码。
一般复杂度较低使用模块(module),复杂度较高使用包(package)来管理代码。而库(library)则是更大的概念,分为标准库、第三方库。
模块(Module)是包含函数和其他语句的脚本文件,是一组Python代码的集合。模块将函数分组放在不同文件来组织编码,便于程序的维护和重用,避免函数名和变量名的冲突。
(自定义函数名尽量不要和内置函数名冲突。查看:Python所有的内置函数)
(自定义模块名尽量不要和内置模块名冲突。如sys模块sys.py
)
创建模块就是将文件保存为扩展名为.py
的文件。
注意事项:
import 模块名
,若成功则说明系统存在此模块。如import abc
是成功的,系统存在该模块。导入模块主要有四种方法:
import 模块名
>>> import time
>>> print(time.localtime())
time.struct_time(tm_yx`ear=2020, tm_mon=8, tm_mday=2, tm_hour=11, tm_min=12, tm_sec=41, tm_wday=6, tm_yday=215, tm_isdst=0)
import 模块名 as 别名
重新定义模块名>>> import time as t
>>> print(t.localtime())
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=2, tm_hour=11, tm_min=14, tm_sec=18, tm_wday=6, tm_yday=215, tm_isdst=0)
from 模块名 import 模块名,模块功能
只导入模块的特定功能>>> from time import time,localtime #只导入time中的localtime()功能
>>> print(localtime())
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=2, tm_hour=11, tm_min=15, tm_sec=41, tm_wday=6, tm_yday=215, tm_isdst=0)
>>> print(time())
1596338146.9064336
from 模块名 import *
导入模块的所有功能>>> from time import *
>>> print(localtime())
time.struct_time(tm_year=2020, tm_mon=8, tm_mday=2, tm_hour=11, tm_min=17, tm_sec=25, tm_wday=6, tm_yday=215, tm_isdst=0)
导入模块是使用模块的第一步。下面以内建的sys
模块为例来编写新的模块Hello
#!/usr/bin/env python3 #标准注释:该文件可直接在Unix/Linux/Mac系统上运行
# -*- coding: utf-8 -*- #标准注释:.py文件本身使用标准UTF-8编码
' a test module ' #该字符串表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释
__author__ = 'Michael' #使用__author__变量署名
import sys #导入sys模块
def test():
args = sys.argv
#调用sys模块中的argv变量,用list存储了命令行的所有参数。
#其中argv第一个参数固定为该.py文件的名称。
if len(args)==1:
print('Hello, world!')
#当参数只有一个,即只有文件名时,输出'Hello, world!'
elif len(args)==2:
print('Hello, %s!' % args[1])
#当参数有两个,输出'Hello,args[1]'。
#args[1]为列表第二位的变量。
#'Hello, %s!' % args[1] 表示输出args[1]的字符串,%s表示将整数转化为字符串。
else:
print('Too many arguments!')
#将特殊变量__name__设置为__main__,若从其他地方导入该模块,if判断失败。
if __name__=='__main__':
test()
其中1-6行是Python模块的标准文件模板。
每个Python程序在运行时都有一个__name__
属性,程序通过对__name__
的判断,能使程序作为导入模块和独立模块都能正确运行。
若程序作为模块被导入,则__name__
属性被设置为模块名;若程序独立运行,则__name__
属性被设置为__main__
。
一般来说,将模块主要功能以实例形式放在if __name__=='__main__':
语句中,能够方便测试模块。
$ python3 hello.py
Hello, world!
$ python hello.py Michael
Hello, Michael!
Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> import hello
>>>
此时没有打印Hello, world!
是因为没有执行test()
函数,需要调用hello.test()
。
>>> hello.test()
Hello, world!
注意模块存储路径相同才能互相导入。或者将模块放入系统默认模块查找的路径
Windows系统默认路径为Python安装目录及其子目录,如lib、lib\site-packages、dllls等。
Linux默认路径为/usr/lib、/usr/lib64及其子目录。
如果加载模块时搜索不到对应.py文件而报错时,可以利用sys
模块的path
变量进行搜索当前目录、内置模块目录和外部模块目录。
这是我Windows系统的目录,之前安装的VisualStudio安装了Python。
>>> import sys
>>> sys.path
['', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\Lib\\idlelib', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\python37.zip', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\DLLs', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\lib', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64', 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\lib\\site-packages']
添加路径主要有三种方法。
sys.path
,添加目录>>> import sys
>>> sys.path.append('C:\Users\chan\Desktop')
这种方法在运行时修改,结束后失效。
PYTHONPATH
.bash_profile
文件$ gedit .bash_profile
添加类似以下内容,Python会添加路径下的模块
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3/site-packages
.pth
以Linux系统为例,打开/usr/local/lib/python3/site-packages文件夹
在文件夹新建文件,内容为要添加的路径,保存为后缀名为.pth
的文件
当复杂度上升时,为了避免模块名冲突,可以利用包(Package)来按目录组织模块。
abc.py
和xyz.py
。但是这两个模块与其他模块名字有冲突。可通过包来组织模块,即选择顶层包名,按目录存放。此时abc.py
模块名就变成mycompany.abc
而xyz.py
就变成mycompany.xyz
每个包都必须含有__init__.py
文件,否则此目录为普通目录而不是一个包。__init__.py
可以是空文件,也可以有代码。因为__init__.py
本身也是一个模块,其模块名为mycompany
。
文件www.py
的模块名就是mycompany.web.www
,两个文件utils.py
的模块名分别是mycompany.utils
和mycompany.web.utils
包可以理解为包含多个模块的文件夹,但是本质仍然为模块。
创建包分为两步:
__init__.py
的文件,可以是空文件,也可以有代码。前文讲到,该文件也是一个模块,模块名为包名。创建包后,可以向包添加模块或包。
__init__.py
文件,里面编写以下代码:def test()
print('This is my package')
在包中添加两个模块,分别为module1.py和module2.py
#module1.py模块文件
def display(argv):
print(argv)
#module2.py 模块文件
class Printdata:
def display(self):
print("This is module2")
由于包的本质也是模块,因此导入包的方法与导入模块的方法类似,主要可以分为三种:
import 包名<.模块名 >
>>> import my_package.module1 as m1
>>> my_package.module1.display("Hello")
Hello
>>> m1.display("Hello")
Hello
执行模块成员(变量、函数或类等)的格式为: 包名.模块名.方法名
或者 别名.方法名
直接导入包,并不会将所有模块导入程序,只是导入名执行__init__.py
文件
>>> import my_package
>>> my_package.test()
This is my package
from 包名 import 模块名
可以从包中导入特定模块
>>> from my_package import module1 as m1
>>> module.display("Hello")
Hello
>>> m1.display("Hello")
Hello
该方法使用成员时不需要带包名前缀,只需要带模块名或别名前缀:模块名.方法名
或者 别名.方法名
其中,from 包名 import *
与import 包名
作用一样,只导入__init__.py
文件并执行。
from 包名.模块名 import 成员名
>>> from my_package.module1 import display as dis
>>> display("Hello")
Hello
>>> dis("Hello")
Hello
使用时直接使用成员名即可,或者使用别名。
其中,from 包名.模块名 import *
可以导入该模块下的所有成员。
====================================================================
Python学习的内容参考
《Python编程:从入门到实践》-[美] Eric Matthes
《21天学通PYTHON》
莫烦Python
廖雪峰的Python教程
Python创建包,导入包
等