python中关于模块,包以及import的学习

来源:互联网 发布:女生学php好找工作吗 编辑:程序博客网 时间:2024/06/05 16:45

一:python中的模块和包

 模块:  如果你从 Python 解释器退出后再重新进入, 那么你之前定义的所有 (函式和变量) 都将丢失. 因此, 如果你想写一个更长的程序, 你最好离线地使用文本编辑器保存成文件,替代解释器的输入来运行. 这称作创建一个 脚本 . 当你的程序变得更长, 你可能想把它分割成几个文件以能够更简单地维护. 你也许还想在几个下同的程序里使用写过的程序, 而不用把一坨代码拷来拷去.为此 Python 提供了方法, 能使用户把定义存放在文件里, 同时又能在脚本或交互式环境下方便的使用它们. 这样的文件称为 模块 ; 一个 模块 中的定义可以 导入(import) 到另一个模块或 主 模块 ( 主 模块是执行脚本的最上层或计算模式下的一组可访问变量的集合).模块就是包含 Python 定义和语句的文件. 文件的名字就是这个模块名再加上 .py. 在一个模块中, 模块的名字 (一个字符串) 可以通过全局变量 __name__ 得到.

包: 包是一个有层次的文件目录结构,它定义了由n个模块或n个子包组成的python应用程序执行环境。通俗一点:包是一个包含__init__.py 文件的目录,该目录下一定得有这个__init__.py文件和其它模块或子包。包对应于文件夹,使用包的方式跟模块也类似,唯一需要注意的是,当文件夹当作包使用时,文件夹需要包含__init__.py文件,主要是为了避免将文件夹名当作普通的字符串。__init__.py的内容可以为空,一般用来进行包的某些初始化工作或者设置__all__值,__all__是在from package-name import *这语句使用的,导出在__all__声明过的模块。

二:模块的搜索路径

python在执行import语句时,到底进行了什么操作,按照python的文档,它执行了如下操作:

第1步,创建一个新的,空的module对象(它可能包含多个module);
第2步,把这个module对象插入sys.module中
第3步,装载module的代码(如果需要,首先必须编译)
第4步,执行新的module中对应的代码。(这里提醒我们Python模块中的代码在被导入时会被执行一次,但是只有在第一次被导入时才会被执行)

第三步查找module的过程

在import的第一个阶段,主要是完成了查找要引入模块的功能,这个查找的过程如下:

检查 sys.modules (保存了之前import的类库的缓存),如果module被找到,则⾛到第二步。

检查 sys.meta_path。meta_path 是一个 list,⾥面保存着一些 finder 对象,如果找到该module的话,就会返回一个finder对象。

检查⼀些隐式的finder对象,不同的python实现有不同的隐式finder,但是都会有 sys.path_hooks, sys.path_importer_cache 以及sys.path。
抛出 ImportError。

三:导入模块
通过以下实例来讲解导入,下面是一个project的结构图:(注:以下是在自定义的包中操作)

project/  packagea/     __init__.py     a.py  packageb/     __init__.py     b.py     bb.pymain.py

1. 如果想要调用同一个包里面的其他模块,如在packageb的bb.py中调用b.py的函数,需要使用如下方式导入:
from packageb import b
或者
import b
(经过测试,这种写法在pycharm中,会提示找不到模块b,但是你可以不用管这个,实际上可以运行)

2. 如果想要在不同包中调用其他模块中的函数,如在packageb的b.py中调用packagea中a.py的函数,需要使用如下方式导入:
from packagea import a
或者
import packagea.a`

3. 如果想要在外面的main.py中调用包中的函数或模块,如在mian.py中调用packageb中b.py的函数,需要使用
from packageb import b
或者
import packageb.b`

4. 如果想要将一个包中的所有模块导入到另一个模块中,如要在main.py中导入packageb中所有的模块,需要使用:
from packageb import *
(注意:需要在packageb的__init__.py文件加入__all__=[“需要导入的模块名”])

`5. 如果使用下面的语句进行导入:

import packageb`packageb.bb.fuc() #这个会报错

上面的这个import语句只会执行__init__.py文件,而不会导入任何模块。不过既然会执行__init__.py文件那么我们可以在改文件中来进行一些操作。如

# packageb# __init__.pyimport b,bb

注意:无论一个包的哪个部分被导入, 在文件__init__.py中的代码都会运行.这个文件的内容允许为空,不过通常情况下它用来存放包的初始化代码。导入过程遇到的所有 __init__.py文件都被运行.

四.相关笔记:

1. 相对引入:relative import 也叫作相对引入,在Python2.5及之前是默认的引入方法。它的使用方法如下:

from .string import afrom ..string import afrom ...string import a

这种引入方式使用一个点号来标识引入类库的精确位置。与linux的相对路径表示相似,一个点表示当前目录,每多一个点号则代表向上一层目录。

2. 我们来看看下面这段代码:

# test.pydef fuc():    print("in fuc")print("in file test")if __name__=="__main__":    fuc()

一个模块既可以当作单独的脚本执行,也可以当作模块被导入使用。当作为单独的脚本使用时,全局变量__name__被置为__main__,if条件成立,那么会执行if条件中的内容,这个作用可以用来测试脚本代码。

当作为模块被导入使用时,__name__就会被置为模块名,而根据上面第二个说明,我们知道系统会执行一次该模块的代码,此时print会输出内容,而if条件不成立就不会在被执行了。

3. 如果一个模块如果定义有列表__all__,则from module import *语句只能导入__all__列表中存在的对象。如:

# test.py__all__ = ["fuc1","fuc2"]def fuc1():    print("in fuc1")def fuc2():    print("in fuc2")def fuc3():    print("in fuc3")

此时如果在其他模块使用 from test import * ,那么只能导入fuc1 和 fuc2这两个函数。

参考:
http://docspy3zh.readthedocs.io/en/latest/tutorial/modules.html#tut-modulesasscripts
http://www.cnblogs.com/ptfblog/archive/2012/07/15/2592122.html
http://blog.csdn.net/waleking/article/details/7600416
https://neo1218.github.io/python-import/
http://www.voidcn.com/blog/u010786109/article/p-3168626.html

0 0