概述
在多人开发项目时,不可能 将所有的模块(即 .py文件)放在 同一个 文件夹中
就像安装QQ、office、wps、游戏等软件,文件要放在不同的文件夹里
QQ安装目录:
包
python引入了“包”(package),用于 组织 多个模块(.py文件)
包 在文件系统中就是 文件夹 ,但必须有 __init__.py 文件
在python3.3 开始,没有 __init__.py 文件也可以
命名方式
同变量命名方式相同,小写字母,后面可以有 下划线_ 和 数字
包结构
包名
|----__init__.py
|----模块名.py
注意:
- 包文件夹内要有 __init__.py 的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包
- __init__.py 可以是 空文件,也可以有 Python代码
- 引入包时,会 先执行 __init__.py 文件
例子
工程目录如下:
project
|---main.py
|---user
|----__init__.py
|---users.py
|---reg.py
|---login.py
users.py,代码如下:
# coding=utf-8
users={}
reg.py
代码如下:
# coding=utf-8
from .users import users
def reg_user(username,password):
global users
if username in users.keys():
print("%s 已经存在,不能注册!"%username)
else:
users[username]=password
print("%s 注册成功!"%username)
if __name__ == "__main__":
reg_user("luhan","123456")
reg_user("lixian","000")
reg_user("luhan","111111")
注意:
由于代码from .users import users,执行该文件报错,但在包外部import正常执行
login.py
代码如下:
# coding=utf-8
from .users import users
def login_user(username,password):
global users
pwd=users.get(username)
if password==pwd:
print("%s 登录成功!"%username)
else:
print("%s 登录失败!"%username)
if __name__ == "__main__":
login_user("luhan","123456")
注意:
由于代码from .users import users,执行该文件报错,但在包外部import正常执行
__init__.py,代码如下:
#coding=utf-8
print('user.__init__.py')
from . import reg,login
注意:
执行该文件报错,但在包外部import正常执行
main.py
启动文件。
注意:
- 在不同包之间import模块,启动文件位置很重要,否则执行时会报错
- 只有__init__.py导入了reg,login,才能执行
import user就可以调用reg模块的函数
# coding=utf-8
import user
user.reg.reg_user("luhan","123456")
user.reg.reg_user("lixian","111111")
user.reg.reg_user("luhan","888")
# user.login.login_user("luhan","123456")
# user.login.login_user("lixian","888")
while True:
op=input("请选择操作:\n 1. 登录 \n 2. 注册 \n请输入序号:")
if op=="1":
username=input("请输入登录名:")
password=input("请输入密码:")
user.login.login_user(username,password)
elif op=="2":
username=input("请输入登录名:")
password=input("请输入密码:")
user.reg.reg_user(username,password)
else:
print("无效操作")
相对导入
相对导入格式
from .A import B,其中.代表当前模块from ..X import Y,其中..代表上层模块
优点
避免硬编码带来的包维护问题,
例如我们改了某一包的名称,那么其它模块对于其子包的所有绝对导入就不能用了,但是采用相对导入语句的模块,就会避免这个问题
(废弃)例子:
project
|---main.py
|---user
|----__init__.py
|---reg.py
|---login.py
|---goods
|----__init__.py
|---view_goods.py
|---add_goods.py
|---delete_goods.py
|---modify_goods.py
(废弃)例子:
目录如下:
project
|---main.py
|---school
|----__init__.py
|---view.py
|---classes
|----__init__.py
|----view.py
|---student
|----__init__.py
|----view.py
|---room(寝室)
|----__init__.py
|---view.py
1.main.py
启动文件。
注意:
在不同包之间import模块,启动文件位置很重要,否则执行时会报错
2.school.__init__.py,代码如下:
#coding=utf-8
print('school.__init__.py')
3.school.view.py,代码如下:
def show():
print('学校信息')
4.school.classes.__init__.py,代码如下:
#coding=utf-8
print('classes.__init__.py')
5.school.classes.view.py,代码如下:
#coding=utf-8
def show():
print('班级信息')
6.school.student.__init__.py,代码如下:
# encode=utf-8
print('student.__init__.py')
7.school.student.view.py,代码如下:
# encode=utf-8
def show():
print('学生信息')
8.room.__init__.py,代码如下:
#coding=utf-8
print('room.__init__.py')
9.room.view.py,代码如下
# encode=utf-8
def show():
print('寝室信息')
实验
1.main.py导入school.view模块
代码如下:
#coding=utf-8
from school import view
或者
#coding=utf-8
import school.view
执行main.py结果如下:
school.__init__.py
在导入school包时,就调用school包下的 __init__.py
2.main.py调用school.view的show()函数
#coding=utf-8
#从shool包中导入view模块,之后可以直接使用view
from school import view
view.show()
或者
#coding=utf-8
#导入school.view模块,后面都要用school.view
import school.view
school.view.show()
执行main.py结果如下:
school.__init__.py
学校信息
3.接着上面代码,main.py导入school.classes.view模块
代码如下:
#coding=utf-8
from school import view
from school.classes import view
view.show()
执行main.py结果如下:
school.__init__.py
classes.__init__.py
班级信息
由于两次import view,导致后面的view覆盖了上面的from school import view,所以打印的结果是“班级信息”,而不是“学校信息”,
所以在导入包时要注意,为了 避免同名 情况,可以使用as关键字 起别名,改动如下:
#coding=utf-8
from school import view
#通过as关键字起别名
from school.classes import view as cview
view.show()
cview.show()
执行main.py结果如下:
school.__init__.py
classes.__init__.py
学校信息
班级信息
在导入school、classes包时,就调用school和classes包下的 __init__.py
3.school.view.py导入school.student.view模块
学校模块中,需要调用学生模块的功能,此时就需要导入不同包的模块,
school.view.py代码如下:
# encode=utf-8
#增加导入student.view模块
from .student import view #.student表示与当前文件同级的student包
def show():
print('学校信息')
view.show()
执行 school.view.py 结果:
ModuleNotFoundError: No module named '__main__.student'; '__main__' is not a package
报错了
注意:
在导入不同包的模块时,要有入口文件,不能随意执行py文件,会报错
执行 main.py 结果:
school.__init__.py
student.__init__.py
classes.__init__.py
学校信息
学生信息
班级信息
4.school.student.view.py导入room.view模块
school.student.view.py代码如下:
# encode=utf-8
#增加导入room.view模块,..room表示当前文件的上一个目录下的room包
from ..room import view
def show():
print('学生信息')
或者
# encode=utf-8
#增加导入room.view模块,此处是全路径
from school.room import view
def show():
print('学生信息')
执行结果
school.__init__.py
student.__init__.py
room.__init__.py
classes.__init__.py
学校信息
学生信息
班级信息
5.school.student.view.py调用room.view的show()函数
school.student.view.py代码如下:
# encode=utf-8
#增加导入room.view模块,..room表示当前文件的上一个目录下的room包
from ..room import view
def show():
print('学生信息')
#增加调用函数代码
view.show()
执行 main.py 结果:
school.__init__.py
student.__init__.py
room.__init__.py
classes.__init__.py
学校信息
学生信息
寝室信息
班级信息
感谢:
http://www.cnblogs.com/ArsenalfanInECNU/p/5346751.html
