在程序开发过程中,随着代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。为了代码的可维护性和可复用性,我们会编写很多函数和类,并对这些函数和类进行分组,分别放到不同的文件里,这样每个文件中所包含的代码量就少很多。
很多编程语言都采用这种组织代码的方式,而在Python中,这样的一个保存代码、函数或者类的.py文件就被称为一个模块(Module)。
又由于不同的开发编写的模块名可能会相同,为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。
模块/包分为三种:
内置模块:如str,time,os 等等;
第三方模块:如WebDriver、requests等,第三方模块可以使用pip install命令安装,也可以通过setup.py文件安装;
自定义模块:模块名要遵循Python变量命名规范,不要使用中文、特殊字符;模块名不要和内置模块名或者是已经安装的第三方模块名冲突。
导入模块
在Python中使用import、from......import、reload导入或者重载模块,在导入模块时只能使用模块名,而不是使用带.py后缀的模块文件名。当Python导入或者重载模块时,会立即执行模块文件的顶层程序代码(不在函数或者类里面的代码),而位于函数或者类里面的代码直到函数或者类被调用后才会执行。
MyModule.py
print("Hello TestOps!")
def my_hello():
print("Hello world!")
def my_add(a,b):
return (a+b)test.py
import MyModule
print("this is a test")
MyModule.my_hello()
#显示结果:
Hello TestOps!
this is a test
Hello world!导入整个模块:
导入整个模块时使用import module_name 的方式;在使用模块函数时,使用module_name.function_name()的方式:
#导入整个模块
import MyModule
print("this is a test")
MyModule.my_hello()
sum = MyModule.my_add(5,6)
print("5+6="+str(sum))
在导入模块时可以给模块指定别名:
import module_name as mn
导入模块中的部分函数:
from module_name import function_name1,function_name2
通过这种方式可以将模块中所有需要的函数或者类导入到程序中,调用时可以直接使用了,调用代码:
#导入模块的指定函数
from MyModule import my_hello,my_add
print("this is a test")
my_hello()
sum = my_add(5,6)
print("5+6="+str(sum))
#显示结果:
Hello TestOps!
this is a test
Hello world!
5+6=11导入模块中的所有函数:
from module_name import *
通过这种方式可以将模块中所有的函数或者类导入到程序中,调用时可以直接使用了,调用代码:
#导入模块的所有函数
from MyModule import *
print("this is a test")
my_hello()
sum = my_add(5,6)
print("5+6="+str(sum))
#显示结果:
Hello TestOps!
this is a test
Hello world!
5+6=11模块调用
在介绍Python的跨目录调用之前先介绍一下import的工作机制,import语句导入指定的模块时会执行3个步骤:
1、找到模块文件,在模块搜索路径下搜索模块文件,查找顺序为
当前路径
PythonPATH目录
标准链接库目录
2、编译成字节码:文件导入时会编译,因此,顶层文件的.pyc字节码文
件在内部使用后会被丢弃,只有被导入的文件才会留下.pyc文件。
3、执行模块的代码来创建其所定义的对象:模块文件中的所有语句从头至尾依次执行,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性(模块只在第一次导入时才会执行如上步骤,后续的导入操作只不过是提取内存中已加载的模块对象,reload可用于重新加载模块)。
前面我们已经由于不同的开发编写的模块名可能会相同,为了避免模块名冲突,Python又引入了包的概念。当我们将一组模块归并到一个目录中,这个目录即为包,目录名即为包名。我们有如下程序目录结构:

当我们在test.py文件中调用mypackage包下的模块(test.py与mypackage文件夹处于同一目录下),在Python3中是可以直接调用的。
test.py代码为:
#调用当前文件夹下子文件夹中的模块
from mypackage import mycount
from mypackage.myclass import Girls
print("this is a test")
sum = mycount.my_count(2,4,6,8,10)
print("mycount=",str(sum))
lily = Girls("Lily",18)
lily.info()
lily.beauty()在Python2中需要在mypackage中添加一个空的__init__.py文件来标识这是一个包含Python模块的包。
但是我们在test文件夹下的子文件夹mytest文件夹的mynewtest.py文件中调用该模块时会报错。
mynewtest.py代码为:
#调用当前文件夹下子文件夹中的模块
from mypackage import mycount
from mypackage.myclass import Girls
print("this is a test")
sum = mycount.my_count(2,4,6,8,10)
print("mycount=",str(sum))
lily = Girls("Lily",18)
lily.info()
lily.beauty()from mypackage import mycount
from mypackage.myclass import Girls
print("this is a new test:")
sum = mycount.my_count(1,2,3,4,5)
print("mycount=",str(sum))
lily = Girls("Lily",18)
lily.info()
lily.beauty()报错内容为:

原因是因为找不到mypackage包,原因很简单mypackage包根本不在我们之前说的三个路径之下。那应该怎么处理呢?我们只需要把这个包添加到路径之中,让编译器能找到该包/模块就好了。修改代码如下:
#将mypackage包的上一级目录test目录添加到PythonPATH里面来
import sys
import os
sys.path.append("..")
#或者
#sys.path.append(os.path.dirname(os.getcwd()))
from mypackage import mycount
from mypackage.myclass import Girls
print("this is a new test:")
sum = mycount.my_count(1,2,3,4,5)
print("mycount=",str(sum))
lily = Girls("Lily",18)
lily.info()
lily.beauty()
#显示结果
this is a new test:
mycount= 15
The girl's name is Lily.
She is 18years old!
All girl want to be beautiful!
当然我们也可以直接添加mypackage到PythonPath里面来,再直接调用mypackage里的模块:
#将mypackage添加到PythonPATH
import sys
import os
sys.path.append(os.path.join(os.path.dirname(os.getcwd()),"mypackage"))
import mycount
from myclass import Girls
print("this is a new test:")
sum = mycount.my_count(1,2,3,4,5)
print("mycount=",str(sum))
lily = Girls("Lily",18)
lily.info()
lily.beauty()
#显示结果
this is a new test:
mycount= 15
The girl's name is Lily.
She is 18years old!
All girl want to be beautiful!