模块就是程序
编写以下简单代码
print('hello python')
并将py文件保存在c盘的python(假设新建)文件下,通过pycharm的Terminal 或者windom命令窗口调出python解释器并输入以下代码
import sys
sys.path.append('c:/python')
import hello
将看到以下输出结果
hello python
用py内置函数dir演示此行代码是如何被打印的。
可以看到初次调用python解释器时会显示一个列表。当导入内置模块sys时再次调用dir()函数会发现列表中多了一个元素sys。但这并不是我们想要的,继续向下看。
当通过sys的path函数拼接出我们在c盘python文件路径后,使用import 导入hello 后 python解释器将打印我们想要的结果'hello python',至此我们再次使用dir()函数会发现此时的列表多了一个以hello命名的元素。由此推断,我们只所以能使用sys.path.append函数和打印出'hello python'是因为我们分别导入一个sys文件和hello文件。这种文件就是python中的模块,文件名就是模块名。
当我们沉浸在理解了什么是python模块时,不小心又敲了一下回车。为什么hello python不见了,难道是py解释器坏了吗?再次打开py解释器重复以上操作会发现只有当第一次import hello时候打印hello python。难道是每按一次回车就打印一次hello python吗?仔细观察代码,我们只写了一行hello python.你可能会想,那我多写几行hello python不就行了吗。试试看,会发生什么。一次性输出了多条hello python 这明显不是你想要的结果。假设你写了一个存储人事信息的系统,每来一个新同事,你都要为他写一个录入程序吗。很显然我们希望只写一次程序,当再有新同事入职时,只需要调用我们写好的程序就可以为新同事办理入职。同理,我们改善我们的代码。
def Register():
print('hello python')
在c:/python文件下替换更新后的hello.py文件。重启python解释器后会发现,按以下步骤操作后发现。hello python终于多次出现了,这就是模块中代码重用。
现在我们知道什么是模块中代码的重用。目前为止,我们只是在一个py文件中定义了一个函数。但一个真实的项目不可能把所有的代码都写在一个模块中对吧。如果你真的要这样做也不是不可以。假设这样一个场景,你写好了一套人事系统,有一天你出国旅游了,老板希望改一下系统的代码,你打电话给同事希望他能帮下忙。但你的代码是由几千甚至上万行组成的。如果你还记得待改的地方和行数,把这两个信息告诉他,他会很乐意帮你完成任务。如果你不记得这些,那你同事就需要把代码通读一遍甚至多遍。如果这样的话,我想没几个人会愿意帮你了,同事恨不得自己重写一遍代码。如果你在编码时将代码封装在多个模块中(比如 数据库连接模块ConnectDB、注册模块Register),你告诉同事你需要在数据库连接模块中把数据库A切换成数据库B。五分钟过后你接到同事的电话,告诉你改好了。这就是接下来要介绍的模块的封装和调用。
检查你的代码是作为程序运行还是被导入到别的程序
在hello1.py中编写以下代码
def hello():
print('I\'m hello1')
hello()
得到输出结果
I'm hello1
此时我们的代码是作为程序运行,并调用hello()函数输出结果,这不难理解。如果我们需要在另外一个程序hello4.py执行时调用hello3.py中的hello()函数,你会怎么做?还记得以下代码的执行过程吗?
import sys
sys.path.append('c:/python')
import hello
现在我们编写hello3.py和hello4.py
hello3.py
def hello():
print('I\'m hello3')
hello4.py
import sys
sys.path.append('E:\PythonStudy\博客专用\模块学习')
import hello3
hello3.hello()
运行hello4程序,得到想要的结果。
I'm hello3
用内置__name__变量判断程序的入口。
修改以上代码,将内置变量__name__添加到hello3中去,查看测试结果。
def hello():
print('I\'m hello3')
print('hello3 name is :', __name__)
右键执行hello3.py 输出结果如下
hello3 name is : __main__
此时右键执行hello4.py输出结果如下
hello3 name is : hello3
I'm hello3
会发现什么?相同的__name__值不一样了。在右键执行hello3和右键执行hello4时,输出的__name__变成了__main__和hello3
这就是模块名和主函数,主函数也就是程序的入口。 得出以下结论,我们在hello3中右键执行程序时程序的入口(主函数)是hello3.py输出结果 hello3 name is : __main__
,而在hello4.py中执行的入口是hello4,输出结果是 hello3 name is : hello3 在hello4.py中被引入的hello3.py的名称被作为模块名使用。此时得到一个新的关键词 __main__。
因此我们可以通过启动程序时判断哪个模块的__name__是__main__来判断程序的入口。
在hello3.py中修改以下代码
def Register():
print('注册用户')
hello4.py中修改以下代码
import sys
sys.path.append('E:\PythonStudy\博客专用\模块学习')
import hello3 if __name__=='__main__':
hello3.Register()
在hello4.py中右键运行,将会看到hello3.py中输出内容。要知道 一个复杂的程序是由很多个模块构成,模块间又互相调用。那么我们在启动程序时,程序的入口在哪。案例中我们用条件判断if __name__=='__main__':时 才开始执行注册函数,也就是程序的入口。
让程序能找到你的模块
现在我们知道,一个写好的模块被导入到其他程序后,可以通过模块名.函数名使用。被导入的前提就是要找到这个模块。下面介绍两种办法找到写好的模块。
一:同目录下模块直接导入。
二:不同目录下模块间使用sys拼接导入。
打开python解释器安装路径》lib》sit-packages文件夹,将写好的模块存放在这个文件夹后,自定模块就可以像import sys一样直接导入而不用拼接存储路径。
但是如果这样做的话,我们的安装文件夹会随着存放的自定义模块的增加而变的越来越大,我们并不想这样做。因此理想的解决办法是将模块的存放路径放在我们的python环境变量中。这样我们就可以将自定义模块存放在任何位置且不影响我们python默认安装文件夹。
三:不同目录下模块间使用pth文件引入模块(常用)
实现目标,导入父包下的模块和父包下子包的模块。 准备工作:
1:工作目录下创建父包 father_package
2:在父包下创建父模块fatherModule 并编写测试代码
def callFatherModule():
print('成功调用父包FatherPackage下的fatherModule')
3:在父包下创建子包childPackage之后在创建子包模块childModule 并编写测试代码
def callChildModule():
print('成功调用父包father_package下子包child_Package的childModule模块')
四:随便创建一个测试py文件,使用site包查看python解释器工作目录
import site
print(site.getsitepackages())
五:创建pth文件存储刚才创建的父包路径,如图使用下面的。
之后就可以在刚才的测试py文件中使用以下方法输出想要的结果。
import fatherModule #引入父级包下模块
fatherModule.callFatherModule()
from childPackage import childModule #引入父级包下包含子包模块
childModule.callChildModule()
输出结果:
成功调用父包FatherPackage下的fatherModule
成功调用父包father_package下子包child_Package的childModule模块