1、模块
模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test)
包:用来从逻辑上组织模块的,本质就是一个目录(必须带有一个__init__.py文件)
导入:
1、import的使用:
1 #模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下
2
3 #test.py
4 import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
5 importspam6 importspam7 importspam8
9 '''
10 执行结果:11 from the spam.py12 '''
ps:我们可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
2、为模块名起别名:为已经导入的模块起别名的方式对编写可扩展的代码很有用
importspam as smprint(sm.money)
有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
1 #mysql.py
2 defsqlparse():3 print('from mysql sqlparse')4 #oracle.py
5 defsqlparse():6 print('from oracle sqlparse')7
8 #test.py
9 db_type=input('>>:')10 if db_type == 'mysql':11 importmysql as db12 elif db_type == 'oracle':13 importoracle as db14
15 db.sqlparse()
假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块
1 if file_format == 'xml':2 importxmlreader as reader3 elif file_format == 'csv':4 importcsvreader as reader5 data=reader.read_date(filename)
3、在一行导入多个模块
import sys,os,re
4、使用模块之from ... import...
1 from spam importread1,read22 from spam import read1 as read #也支持as
3 from spam import read1,read2,money #一行导入多个名字
4 from spam import * #把spam中所有的不是以下划线(_)开头的名字都导入到当前位置
5
6 #大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
5、from...import 与import的对比
import本质:把导入的模块代码全部赋值给一个新的变量,调用时 变量名.方法
from import 本质:把原模块代码复制到当前目录,调用时 方法()
1 #唯一的区别就是:使用from...import...则是将spam中的名字直接导入到当前的名称空间中,所以在当前名称空间中,直接使用名字就可以了、无需加前缀:spam.
2
3 #from...import...的方式有好处也有坏处
4 好处:使用起来方便了5 坏处:容易与当前执行文件中的名字冲突
验证一:当前位置直接使用read1和read2就好了,执行时,仍然以spam.py文件全局名称空间
1 #测试一:导入的函数read1,执行时仍然回到spam.py中寻找全局变量money
2 #test.py
3 from spam importread14 money=1000
5 read1()6 '''
7 执行结果:8 from the spam.py9 spam->read1->money 100010 '''
11
12 #测试二:导入的函数read2,执行时需要调用read1(),仍然回到spam.py中找read1()
13 #test.py
14 from spam importread215 defread1():16 print('==========')17 read2()18
19 '''
20 执行结果:21 from the spam.py22 spam->read2 calling read23 spam->read1->money 100024 '''
验证二:如果当前有重名read1或者read2,那么会有覆盖效果。
1 #测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
2 #test.py
3 from spam importread14 defread1():5 print('==========')6 read1()7 '''
8 执行结果:9 from the spam.py10 ==========11 '''
验证三:导入的方法在执行时,始终是以源文件为准的
1 from spam importmoney,read12 money=100 #将当前位置的名字money绑定到了100
3 print(money) #打印当前的名字
4 read1() #读取spam.py中的名字money,仍然为1000
5
6 '''
7 from the spam.py8 spam->read1->money 10009 '''
6、包
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
需要强调的是:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
注意事项:
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,
点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,
点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
2、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
3、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
7、模块搜索路径
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
导入模块的本质就是把python文件解释一遍,然后赋值给模块名,(import test 相当于 test='test.py all code')
导入模块的过程:找文件,找文件所在的路径,找sys.path
所以 我们需要把当前脚本的绝对路径的父父路径,加到sys.path里去,这样就可以找到其他模块。
所以我们引入一个新模块os,os.path.abspath(__file__)可以获得当前模块的绝对路径
然后再通过os.path.dirname可以获取到除文件名以外的路径,我们使用2次,就可以得到父父级目录,现在我们获得了父父级目录,我们把目录加到 sys.path去,但是我们注意我们需要把这个目录放到列表sys.path的第一个位置去~!
导入包的本质就是执行该包下面的__init__.py文件
8、os路径处理
1 os路径处理2 #方式一:推荐使用
3 importos4 #具体应用
5 importos,sys6 possible_topdir =os.path.normpath(os.path.join(7 os.path.abspath(__file__),8 os.pardir, #上一级
9 os.pardir,10 os.pardir11 ))12 sys.path.insert(0,possible_topdir)13
14
15 #方式二:不推荐使用
16 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))