10、Python之模块
模块
1、模块的定义:用来从逻辑上组织python代码来实现一个特定的功能,本质上就是以.py结尾的python文件。
2、模块的导入方法:
假设有2个模块module_01和module_02,其代码如下:
1 #module_01模块 2 module_name = "module_01" 3 def sayHi(call_name): 4 print("在module_01中执行,被%s调用" % call_name) 5 def logger(): 6 print("logger in the %s" % module_name)
1 #module_02模块 2 module_name = "module_02" 3 def sayHi(call_name): 4 print("在module_02中执行,被%s调用" % call_name) 5 def logger(): 6 print("logger in the %s " % module_name)
1、import module_name (导入单个模块module_name)
1 #main 模块 2 import module_01 #导入module_01模块 3 module_name = "main" 4 module_01.sayHi("main") #执行结果在module_01中执行,被main调用
2、import module_name,module2_name(导入多个模块module_name,module2_name)
#main 模块 import module_01,module_02 #导入module_01,module_02模块 module_name = "main" module_01.sayHi("main") #执行结果在module_01中执行,被main调用 module_02.sayHi("main") #在module_02中执行,被main调用
3、from module_name import *(导入module_name模块中的所有代码,慎重)
1 #main 模块 2 from module_01 import * 3 module_name = "main" 4 sayHi(module_name) #执行结果 在module_01中执行,被main调用 5 logger() #执行结果 logger in the module_01
注意,这种导入方式本质上是将module_01的所有代码复制一份,放在main模块中,所以在调用module_01模块中的变量和函数时,不需要加模块名。那为什么要慎用呢,让我们对main模块中的代码进行修改一下。
#main 模块 from module_01 import * module_name = "main" def logger(): print("logger in the %s" % module_name) logger()
此时调用logger函数时,执行的结果应该是logger in the main。也就是说执行了mian模块中的looger函数而不是module_01。根据上面说的from module_01 import *这种导入方式就是将模块中的所有代码放到mian模块中,因此上面main模块的代码又等价于
1 #main 模块 2 #from module_01 import * 3 #--------------module_01模块的代码------------------ 4 module_name = "module_01" 5 def sayHi(call_name): 6 print("在module_01中执行,被%s调用" % call_name) 7 #----------------mian模块的代码-------------------- 8 def logger(): 9 print("logger in the %s" % module_name) 10 module_name = "main" 11 def logger(): 12 print("logger in the %s" % module_name) 13 logger()
对于变量module_name来说,代码的第4行赋值值为"module_01",然后在代码的第10行又赋值为"main",所以module_name的值就是"main",由于函数名及变量名,所以logger函数也是同样的道理。那么问题来了,如果此时main函数的代码是这个样子的:
#main 模块 module_name = "main" def logger(): print("logger in the %s" % module_name) from module_01 import * logger()
执行的结果会是神马样子呢?
4、from module_name import m1,m2(导入模块module_name中m1,m2)
此类导入省去,太简单我都不好意思说了
5、from module_name import m1 as m1_test (导入模块module_name中m1并修改m1的名字为m1_test)
之前第3种导入方式存在的一个问题是,如果main模块中也定义了looger函数,这时候就会和module_01模块中的looger相互覆盖,第5种导入方式就是为了解决这个问题:
1 #main 模块 2 module_name = "main" 3 from module_01 import logger as module_01_logger 4 def logger(): 5 print("logger in the %s" % module_name) 6 logger() #执行结果 logger in the main 7 module_01_logger() #执行结果 logger in the module_01
6、import package_name(导入包)
python中包的含义本质上就是带有__init__.py文件的目录,而导入包之后,只能调用该包的__init__.py文件中的函数和变量。例如:
1 #package_01中的__init__.py 2 def logger(): 3 print("logger in the package_01__init__.py")
main模块中的代码如下:
#main 模块 import package_01 package_01.logger() #执行结果 logger in the package_01__init__.py
这时,我们在package_01增加一个模块package_module_01,代码如下:
1 #package_01包下面的package_module_01.py 2 def logger(): 3 print("logger in the package_module_01.py")
这时候,我想在模块中调用package_module_01中的logger方法,main模块的代码如下:
#main 模块 import package_01 package_01.package_module_01.logger() #执行结果 报错:AttributeError: module 'package_01' has no attribute 'package_module_01'
纳尼?报错了,悲剧了!正如我们之前说的,对于包的导入而言,我们只能调用__init__.py中的变量和函数,我们如果需要调用package_module_01中的变量和函数时,就需要借助__init__.py来做一个桥梁,我们先在__init__.py中导入package_module_01。使用语句:from .import package_module_01,这时候我们再执行main模块就成功了。
7、动态导入模块
有时候,我们需要动态导入模块,这时就需要使用标准模块importlib来实现。具体代码如下:
1 import importlib 2 aa = importlib.import_module("lib.aa") 3 print(aa.name)
其中“lib.aa”是指lib包下aa模块,在aa模块下有一个name变量,通过行2的代码就可以动态导入模块,然后对其模块中的数据和方法进行访问。
3、路径搜索
上面我们说的模块和包的导入都是基于各个模块在同一个目录上,那么,如何处理不同目录之间模块的导入呢?其实我们说,模块的导入是分2步完成的,路径搜索和模块处理,下面我们看如何导入其它目录的模块。
假设有2个目录dir_01和dir_02,其中dir_01中有一个模块module_01,module_01中有一个logger函数,dir_02中有一个模块module_02,我们的需求是在module_02中导入module_01调用其logger函数。
#dir_01目录下的module_01模块 def logger(): print("logger in the module_01")
1 #dir_02目录下的module_02模块 2 import sys,os 3 DIR_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 sys.path.append(DIR_PATH) 5 from dir_01 import module_01 6 module_01.logger() #执行结果 logger in the module_01
其中sys,os都是系统标准的模块,__file__获取当前文件的相对路径,os.path.abspath()获取文件的绝对路径,os.path.dirname()获取当前目录的上级目录,sys.path.append()将路径添加到系统的环境变量中。这时候我们再使用模块导入语句:from dir_01 import module_01就可以找到module_01模块了。
4、模块分类:
模块分为三种:
- 自定义模块(咱们上面写的全是自定义模块)
- 内置标准模块(又称标准库 os,sys都是内置模块)
- 开源模块(一些大牛写的比较好的模块)