python之模块

一、模块的定义与分类

1. 模块的定义

  • 分文件: 10个文件.每个文件有50个函数,将一些功能相同或相似的函数,放在一个文件中,随用随拿,可以解决代码冗余,重复性,我们应该将这10个函数提取出来,放在一个文件中,随用随拿.
  • 一个模块就是一个py文件,这个模块存储很多相似的功能,相似的函数的集合体.

2. 模块的优点

  • 节省代码.
  • 容易维护,组织结构更清晰.
  • 拿来主义,提高开发效率.

3. 模块的分类

  • 内置模块,标准库.python解释器自带的,time,os,sys,等等.200多种.
  • 第三方库(模块),各种大神写的一些模块,通过pip install....安装.6000种.
  • 自己写的模块.自定义模块.

例题

1. 整2个文件,文件1是模块文件,文件2是执行文件
让2调用1中模块进行执行
2. 导入某一个功能或者函数
from xxx import 相当于复制一份过来,容易覆盖当前的变量
整2个文件from tbjx import name
from tbjx import read1

3. change
# 执行文件的效果
from tbjx import name
from tbjx import change
change()
print(name)
# 输出结果
太白金星 # 正常输出的应该是barry
# 模块文件的效果
补全代码
# 3总结:如果引用模块中的函数,如果此函数用到一些变量,这些变量还是从此模块中寻找,不会改变您当前执行文件的变量,这种情况是极值情况(工作中完全用不到)
# 如果你要引用一些模块的变量,你的模块名字 补全内容

流程控制语句__name__之所以能作为流程分流 但脚本运行和模块被引用的时候功能完全不一样

最后一个模块的搜索路径

凭什么我直接import time能找到这个模块

寻找模块的路径 内存—>内置模块—> sys.path中找

二、模块的导入(import)

1.导入方法

# import tbjx
# # 当我引用tbjx模块的时候,实际上将tbjx.py执行一遍,加载到内存.
# import tbjx
# import tbjx
# import tbjx
# import tbjx
# import tbjx

# 只是第一次引用时,将此模块加载到内存.

2.第一次导入模块发生的三件事

  1. 将tbjx.py文件加载到内存.
  2. 在内存中创建一个以tbjx命名的名称空间.
  3. 通过tbjx名称空间的名字.等方式引用此模块的名字(变量,函数名,类名等等).

3.执行方法

模块名加点的方式执行模块功能

import tbjx
n = 1
# print(tbjx.name)
# tbjx.read1()
# tbjx.read2()

4.被导入模块有独立的名称空间

# 坑:通过tbjx.的方式引用此模块的名字时,一定一定是从此模块中寻找.
# 通过import 引用模块 他有自己的独立名称空间,与当前执行文件没有关系.
name = '李业'
print(tbjx.name)

def read1():
    print('in 02 模块import')

tbjx.read1()

# 输出结果
太白金星

5.为模块起别名(alias)

优点:

  • 简单,便捷.
  • 有利于代码的简化

起别名方法

import cStringIO as ci
# 将cStringIO这么长的模块名给他起了个别名,用起来方便

起别名后的调用方法

import 模块名 as 别名	   #导入模块中的所有成员
别名.变量名		  	      #调用模块中的一个变量
别名.函数名()	 		  #调用模块中的一个函数
模块名.变量名		  	      #错误!!!这样调用将报错!!!
模块名.函数名() 	 		  #错误!!!这样调用将报错!!!
from 模块名 import 变量名 as 别名1, 函数名 as 别名2
别名1
别名2()
变量名			#错误!!!这样调用将报错!!!
函数名()		#错误!!!这样调用将报错!!!

练习题

# 原始写法
result = input('请输入')
if result == 'mysql':
     import mysql1
     mysql1.mysql()
 elif result == 'oracle':
     import oracle1
     oracle1.oracle()
 list.index()
 str.index()
 tuple.index()

# 起别名
 result = input('请输入')
 if result == 'mysql':
     import mysql1 as sm
 elif result == 'oracle':
     import oracle1 as sm
 ''' 后面还有很多'''
 sm.db()  # 统一接口,归一化思想
 # 通过输入不同的数据库名称执行不同的模块中的代码

三、导入多个模块(from…import...)

1.导入和调用方法一

import time
import os
import sys

模块名.变量名		  	      #调用模块中的一个变量
模块名.函数名()	 		  #调用模块中的一个函数

2.导入和调用方法二

from tbjx import name  # 从tbjx模块导入name功能
from tbjx import read1 
from tbjx import read2
print(name)
print(globals())
read1()

变量名					  	  	    #调用模块中的该变量 直接变量名
函数名()	 			    	    #调用模块中的该函数 直接函数名

注意: 这种方法于在调用时不需要使用前缀,可能会导致其与当前脚本中的成员命名冲突(后出现的成员会覆盖先出现的同名成员),对此可考虑使用别名

3.from ... import ... 与import对比

优点: from.. import 因为不用加模块名用起来更方便

from tbjx import name
print(name)

缺点: 容易与本文件的名字产生冲突

#容易产生冲突,后者将前者覆盖
name = 'alex'
from tbjx import name
print(name)

4.导入模块时的查找顺序

  • 内存中:如果这个模块已经成功加载过,就不会重复加载,直接使用内存中的
  • 内置路径中:python安装路径下(Lib)
  • PYTHONPATH:import时寻找模块的路径。
  • sys.path:是一个路径的列表。
  • 如果上面都找不到,就报错。

查看被加载的模块

import sys
print(sys.modules)


#输出结果
{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>,} 
#以字典的形式存在

5.sys.path及将自定义模块导入的方法

获取当前系统中查找模块的路径

import sys
print(sys.path)

#输出结果
['D:\\My Documents\\Pycharm', 'D:\\My Documents\\Pycharm', 'D:\\Program Files\\Python\\python36.zip', 'D:\\Program Files\\Python\\DLLs', 'D:\\Program Files\\Python\\lib', 'D:\\Program Files\\Python', 'D:\\Program Files\\Python\\lib\\site-packages', 'D:\\Program Files\\PyCharm\\helpers\\pycharm_matplotlib_backend']

说明:

  1. 列表的第一个元素始终是被执行的py文件所在的目录,因此当前py文件所在的路径中的模块始终是可以被直接使用的,第二个元素始终是当前的项目路径
  2. 系统自带的模块的路径也在其中,这也就说明了为什么在程序中能自由的使用内置模块.
  3. 系统从前往后依次寻找被导入模块,则路径中如果出现重名的模块,前面的会先生效,这也是为什么我们自定义的模块不要和系统内置的模块同名的原因(将会导致内置模块被覆盖)

值得注意的是,sys.path中出现的路径的子目录并不会被查找到,对此有三种解决方案:

  1. 把我们自定义的模块放到系统默认的路径中,如D:\Program Files\Python\lib
  2. 在环境变量中定义PYTHONPATH,在其中保存被导入模块的路径
  3. 手动修改sys.path表示的列表,将自定义的模块的路径添加到其中
    第一种方案并不好,因为会污染系统自带的模块库
    第二种方案也不好,因为系统环境变量的改变会影响到其他的项目
    第三种方案是通常的做法,既不会污染系统内置路径也不会影响其他项目,只在当前项目中有效.

添加模块路径到默认路径中

假设当前脚本为main.py,想要调用test_module3.py模块中的func3函数

#三步走
#第一步: 先获取当前py文件的绝对路径
print(__file__) 

执行结果:
D:/test011/bin/main.py

#第二步: 再获取test_module3.py这个模块的绝对路径
import os
print(os.path.dirname(__file__))

执行结果:
D:/test011/bin

#第三步: 最后拼接,并将模块路径添加
import os
import sys

sys.path.append(os.path.dirname(__file__) + '/dd')
import test_module3
test_module3.func3()
#注:表示地址时,正斜杠“/”与反斜杠“\”可以混用,此例中,将dd前面的"/"改成"\"也行

6.在from 模块名 import *方式下限制被导入的成员

在被导入的模块中,使用__all__ 属性,它是一个列表,其元素是允许被导入的成员名的字符串。注意:此方式对 import 模块名 及其他所有方式的导入都无效。

# 模块中
__all__ = ['f1','f2']

def f1():
	print('f1')

def f2():
	print('f2')

7.__name__属性(***)

__name__ 是Python内置的一个属性,Python中的函数、模块、类都有这个属性

以脚本方式运行时,__name__值为__main__

以模块方式被导入时,被导入模块中的__name__值为模块名(如my_module)

模块中对模块成员的测试代码的通常写法

# b.py
#Pycharm中if __name__ == '__main__':可用main快速输入
def main():
    可执行语句1
    可执行语句2
    ……
if __name__ == '__main__':
    main()

被别人引用时,名字为模块名(脚本名),脚本方式执行时,名字为main

import b
def a():
    pass
b=a
def c():
    print(b.__name__)
c()

执行结果:
a
注:可以用__name__显示变量指向内存地址所对应的函数名

四、序列化模块

1.序列化模块的用途

将一种数据结构转换成特殊的序列(特殊字符,bytes),并且还可以转换回去

凡是数据通过网络传出去最终的格式必须bytes

2.json模块

用途: 所有编程语言公认的一种序列,

缺点: 支持的python的数据结构有限,只支持: int str bool dict list tuple None 除了(set())

用法一 (两对儿,四个方法)
dumps,loads # 用于网络传输 #原则一对一,一个dumps对应一个loads

# 转换传输
dic = {'username':'太白'}
ret = json.dumps(dic,ensure_ascill=False,sort_keys=True)
print(ret)

# 反转回来
ret_dict = json.loads(ret)
print(ret_dict)
将转换后的特殊字符串写入文件,再从文件中读取出来,再反转回来
import json
dic = {'username': '太白', 'password': 123,'status': False}

with open('register.json',mode='w',encoding='utf-8') as f1:
	ret = json.dumps(dic, ensure_ascii=False)
	f1.write(ret+'\n')
with open('register.json',mode='r',encoding='utf-8') as f2:
	for line in f2:
		ret_dic = json.loads(line)
		print(ret_dic)

# 该题练习主题是: 先将转换写入文件,再从文件中读取出来,反转回来
# register.json内容
{"username": "太白", "password": 123, "status": false}
# 输出结果
{'username': '太白', 'password': 123, 'status': False}
用法二
dump,load # 用于单个数据的存取文件,只能用于单个字典,用法很狭窄
import json
dic = {'username': '太白', 'password': 123,'status': False}
with open('jsonlx1.json',encoding='utf-8',mode='w') as f1:
    json.dump(dic,f1)


with open('jsonlx1.json',encoding='utf-8') as f1:
    dic1 = json.load(f1)

print(dic1,type(dic1))
将多个数据存储到一个文件中
l1 = ['wusir', '太白', '小黑1', 666]
l2 = ['wusir', '太白', '小黑2', 666]
l3 = ['wusir', '太白', '小黑3', 666]
with open('pickle练习1.pickle',mode='wb') as f1:
    pickle.dump(l1,f1)
    pickle.dump(l2,f1)
    pickle.dump(l3,f1)

with open('pickle练习1.pickle', mode='rb') as f1:
    ret1 = pickle.load(f1)
    ret2 = pickle.load(f1)
    ret3 = pickle.load(f1)
    print(ret1,ret2,ret3)

3. pickle模块

用途: 支持python的所有类型和数据对象

缺点: 只能python使用

用法一 (两对儿,四个方法)
dumps,loads # 只能是网络传输用,直接转换成bytes

# 转换传输
l1 = ['wusir', '太白', '小黑', 666]
ret = pickle.dumps(l1)
print(ret)

# 反转回来
l2 = pickle.loads(ret)
print(l2)

用法二
dump,load # 用于单个数据的存取文件,只能用于单个字典,用法很狭窄
l1 = ['wusir', '太白', '小黑', 666]
with open('a.pickle',mode='wb') as f1:
	pickle.dump(l1,f1)

shevle模块(不讲)

用途: 只能是文件存取,shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些

用法

import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open('shelve_file')
existing = f1['key']  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)

五、sys模块

用法

import sys

sys.path ***

sys.version

sys.argv

for i in range(3)
	print(i)
sys.exit(n) # 强制退出

六、OS模块

用法

import os
print(os.getcwd()) # 获取当前的绝对路径
os.chdir(r'/Users/wuqiang/work/PycharmProjects/python23') # 切换目录 相对于shell下cd
print(os.curdir) # 返回当前路径

# 和文件相关
os.makedirs('目录1/目录2')
os.makedirs('dirname1/dirname2/dirname4') #创建多级目录
os.removedirs('dirname1/dirname2/dirname4') #递归删除多级目录
os.mkdir('abc') #创建单级目录
os.rmdir('abc') #删除单级目录
print(os.listdir('/Users/wuqiang/work/PycharmProjects/python23')) #查看目录下文件类似ls
print(os.stat('/Users/wuqiang/work/PycharmProjects/python23')) #获取状态,文件信息
print(os.environ) #获取环境变量

# 路径相关
print(os.path.abspath('day17.py')) # 获取绝对路径
print(os.path.split(os.path.abspath('day17.py'))) #将文件路径和文件名分割
print(os.paty.dirnaem('day17.py'))
print(__file__) #动态获取当前文件的绝对路径
print(os.path.dirname(os.path.dirname(__file__))) #获取爷爷级目录
print(os.path.basename('day17.py')) #获取文件名
print(os.path.exists('day17.py')) # 判断文件是否存在
print(os.path.isabs('/Users/wuqiang/work/PycharmProjects/python23/day17')) #判断是不是绝对路径
print(os.path.isfile('/Users/wuqiang/work/PycharmProjects/python23/day17')) #判断是不是存在的文件
print(os.path.isdir('day17.py')) #判断是否是一个目录
print(os.path.exists('day17.py')) #判断这个路径或文件是否存在
print(os.path.join('/Users/wuqiang/work/PycharmProjects/python23/day17','day17.py'))#将路径和文件拼接在一起
print(os.path.getatime('/Users/wuqiang/work/PycharmProjects/python23/day17'))#最后访问时间
print(os.path.getmtime('/Users/wuqiang/work/PycharmProjects/python23/day17'))#最后修改时间
print(os.path.getsize('/Users/wuqiang/work/PycharmProjects/python23/day17')) #文件的大小

七、hashlib (加密)

用途: 加密模块,摘要算法,散列算法,它是一堆加密算法的集合

  • 密码加密
  • 文件的一致性校验

hashlib如何加密:

  • 将一个bytes类型的数据,通过hashlib进行加密返回一个等长度的16进制数字

  • 过程不可逆

  • 相同的bytes类型的数据通过相同的加密码方法得到的数字绝对相同

  • 不相同的bytes类型的数据通过相同的加密方法得到的数字绝对不相同

密码加密用法:
ret = hashlib.mkd5()
ret.update('123'.encode('utf-8'))
print(ret.hexdigest())
# 输出结果
202cb962ac59075b964b07152d234b70
获取文件md5值函数写法:
def encryption(path):
	import hashlib
	ret = hashlib.md5()
	with open(path, mode='rb') as f1:
		while 1:
			content = f1.read(1024)
			if  content:
				ret.update(content)
			else:
				return ret.hexdigest()
a = encryption('/Users/wuqiang/Downloads/python-3.7.4rc1-embed-win32.zip')
print(a)
#输出结果

加固定盐
ret = hashlib.md5('xxx教育'.encode('utf-8'))
ret.update('123'.encode('utf-8'))
s = ret.hexdigest()
print(s,type(s))

#输出结果
2230499227e2134dc58609d8c8997cd9 <class 'str'>
加动态的盐
username = input('输入用户名:').strip()
password = input('输入密码').strip()
ret = hashlib.md5(username[::2].encode('utf-8'))
ret.update(password.encode('utf-8'))
s = ret.hexdigest()
print(s)
sha系列: 安全系数高,耗时高.加盐,加动态盐
ret = hashlib.sha512()
ret.update('123456fdklsajflsdfjsdlkafjafkl'.encode('utf-8'))
s = ret.hexdigest()
print(s,type(s))
posted @ 2019-06-27 20:37  爱咋闹  阅读(156)  评论(0编辑  收藏  举报