python——包、模块

包、模块的概念

  python中,将文件夹视为一个包,将文件夹(包)的一个文件视为一个模块,一个包下面,可以有多个模块,而每一个模块内部可以有多个变量、类、函数。

  如果要将一个文件夹作为“包”,那么需要在这个文件夹的下一级目录下创建一个文件名为__init__.py的文件。比如,我有一个p1文件夹,我要将这个文件夹作为一个包,那么我就在p1文件夹下创建一个__init__.py问文件即可。这个__init__.py是一个比较特殊的文件,不仅标志着这个所在目录为一个包,而且,当这个包或者这个包中的模块被其他文件导入的时候,会首先运行这个__init__.py文件。

  在导入一个模块的时候,会将这个模块(文件)执行一次。

  包可以嵌套,即,文件夹(包)内部除了文件(模块),还可以有文件夹(包),同样需要遵守上面这个规则。

  下面是一个项目的目录结构:

project
    |—— p1 
        |—— __init__.py
        |—— m1.py
        |—— son
            |—— __init__.py
            |—— m1.py
        |—— index.py
    |—— p2
        |—— __init__.py
        |—— m1.py
    |—— main.py

  上面这个结构中,project有两个包p1和p2,分别有自己的模块m1,虽然模块名称是一样的,但是因为路径不同,所以,模块是不同的。同时p1包中,还一个子包son,son包中也有一个模块m1。

 

导入模块

  使用import关键字,格式如下:

import  package.module

  如果要导入本package中的module,那么可以省略package。

  在main.py中要使用project下的p1和p2包的模块,方法如下:

#main.py
import p1.m1
print(p1.m1.p1_m1)

import p1.son.m1
print(p1.son.m1.p1_son_m1)

import p2.m1
print(p2.m1.p2_m1)

  

  p1目录下的index.py要想使用p1包下的模块时,方法如下:

import m1 #导入的是p1.m1模块,此时不要写p1.m1,因为index.py在p1包内
print(m1.p1_m1)

import son.m1 #导入的是p1.son.m1模块
print(son.m1.p1_son_m1)

  

  如果p1目录下的index.py要想导入p2包下的m1模块,方法如下:

 

 

设置模块别名

  上面可以看出,在导入模块的时候,有使用会因为包的目录层级较深,导致使用模块中的某些变量时,要写很长的路径,解决这个方法,可以在import的时候,加一个as,给模块设置一个别名。

#使用as关键字,给模块设置一个别名
import p1.m1 as p1m1
print(p1m1.p1_m1)

import p1.son.m1 as psm
print(psm.p1_son_m1)

import p2.m1 as p2m1
print(p2m1.p2_m1)

  

导入模块中的部分数据

  有时候,我们在导入模块的时候,不需要导入某个模块中的所有内容,也许只需要其中的一个变量,那么我们可以使用from关键字:

# 格式
# from package.module import var|def|class
from p1.m1 import p1_m1
print(p1_m1)

# from package.module import var|def|class as alias
from p1.m1 import p1_m1 as p
print(p)

# from package import module  #导入某个模块
from p1 import m1
print(m1.p1_m1)  #不需要再使用p1.m1

 

模块中指定导出的数据 

 

  有时候,如果我们想导入某个模块的某部分数据时,虽然可以使用from package.module import xxx,yyy,zzz....但是当数据过多,在import后面写出所有的数据,是很不现实的。

  解决方法是在模块中为__all__变量赋值,值是一个list,内容为要导出的内容。

  比如p1包下面的m1,内容如下:

__all__ = ["p1_m1"]  #设置导出的内容只有p1_m1这个变量

p1_m1 = "bbbbbbbbb"
p1_m11 = "czzzzzzz"

  

  main.py中,尝试使用p1包下面的m1模块中的p1_m1,会成功,但是使用p1_m11时就会失败:

from p1.m1 import *
print(p1_m1)  #访问成功
print(p1_m11) #报错:name 'p1_m11' is not defined

  

导入某个包的所有模块

  假设main.py需要导入p1包下面有m1.py和m2.py两个模块,那么我们可以使用下面方法导入p1下的所有模块:

from p1 import *
print(m1.p1_m1)
print(m2.p1_m2)

  上面这个代码运行之后会报错,错误信息是:找不到m1,说明模块m1导入失败了,这是因为,需要在p1包的__init__.py中,修改__all__变量的值,内容就是要导出的模块名:

# 修改p1/__init__.py文件
print("从p1包中导出数据")
__all__ = ["m1", "m2"]

  然后main.py就可以正常运行了,并且首先输出内容“从p1包中导出数据”,表明再导入模块的时候,会先执行模块所在包目录下的__init__.py文件。

  所以,只要在包下面的__init__.py中的__all__变量中指定要导出的模块名称即可。

 

  

导入python内置标准库

  内置标准库有很多,比如sys,io...

  

__init__.py的功能

  指定包导出的模块

    就是前面在__init__.py中设置__all__变量的值,用来限制其他文件在导入该包中所有模块时,允许导入的模块。

 

  合并要重复导入的包或者模块

  经常有这种情况,我们一个文件夹下有很多python文件,并且每一个模块都需要引入很多相同的系统模块,比如都需要引入os,sys,io模块,有两种方法解决:

  1、在每个文件中都使用import导入3个模块。简单直接,但是有点累,当导入的模块几十上百时,多个文件就会出现大量相同的代码(大量的import语句,每个文件的前100行全是import)。

  2、在该文件夹下面,创建一个包,因为类型是包,所以包下一级会有一个__init__.py文件,所有重复导入的模块都在这里导入;然后在其他文件中,导入这个包即可,因为会首先执行__init__.py文件,也就将需要的模块导入了。

  

包、模块的导入导出注意事项

  1、在导入包或者模块时,对同一个包或者模块重复的导入时,并不会报错,但最好不要重复导入,即使重复导入,模块代码也只会运行一次。

  2、一个模块在导入其他模块的时候,避免出现“循环导入”的情况,比如下面这个情况:

#m1.py
import m2
abc = m2.xyz

#m2.py
import m1
xyz = m1.abc

  当其他文件导入m1或者m2时,就会出错。同样,执行m1或者m2时,也会报错,因为出现了循环导入的情况。

 

posted @ 2018-10-06 22:34  寻觅beyond  阅读(262)  评论(0)    收藏  举报
返回顶部