一 模块导入
1. 模块基础
模块即文件
模块的分类:
- 内置模块;
- 第三方/扩展模块;
- 自定义模块,模块名一定符合变量名的规范
导入多个模块:一行导入一个(规范)
导入顺序:内置模块;第三方;自定义(规范)
导入模块发生了:
- 开辟以模块命名的内存空间
- 执行模块内代码,生成变量字典
重复导入无效果:第一次导入后就将模块名加载到内存,重复导入仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句。sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
不要循环导入
2 . 导入方式:
导入方式大致分为导入func和moudle两类,两者差距不大:都在全局命名空间增加相应的名称;两者都会执行moudle中的执行语句
- import moudle_name (as xxx)
- from package import moudle_name (as xxx)
- from moudle_name import func (as xxx)
- from package.moudle_name import func (as xxx)
from moudle_name import func (as xxx) 的本质是在当前文件的全局变量中加入func名,然后指向moudle_name中的func
#myfile.py #注意文件名符合变量规范 print('the beginning') a = 100 def func(): print(a) #myfile2.py from myfile import func # 该func只是函数名,内存地址还是指向上式中的func a = 200 func()
the beginning;100 #还是会执行导入模块中的语句
3.__name__
3.1 __name__介绍
内置变量,返回当前模块(不是类和函数)的命名空间
文件执行的两种方式:
- 以模块形式导入
- 在pycharm或cmd中以脚本方式直接运行
应用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
全局变量__name_:
- 当文件被当做脚本执行时:__name__ 等于'__main__'
- 当文件被当做模块导入时:__name__等于模块名
3.2 sys.moudles[__name__]和sys.moudles[‘__main__’]区别
反射自身模块(导入模块或者主程序)内容的写法:
getattr(sys.moudles[__name__],func_name),而不是getattr(sys.moudles[‘__main__’],func_name)
__name__是个内置变量,'__main__'是个字符串
#mylife.py
print('the beginning') import sys print(__name__) print(sys.modules['__main__'])
print(sys.moudles[__name__]) #因为__name__是个变量,在sys.moudles应该查询字符串‘__mylife__’
#mylife2.py import mylife import sys print(__name__) print(sys.modules['__main__']) #获取当模块 print(sys.moudles[__name__])
the beginning #导入的文件自动执行 mylife #作为模块导入时,显示模块名'__main__' from 'E:/2019allstark/practice1/1/a002.py'> #模块中的sys.moudles其实主程序的信息
__main__'__main__' from 'E:/2019allstark/practice1/1/a002.py'>
4. 查找路径
根据模块名寻找顺序:内存中已经加载的模块->内置模块->sys.path路径中包含的模块(第三方模块在此处);内存、内置、path
自定义模块切勿与内置模块重名
['E:\\2019allstark\\practice1\\mylife', #当前目录路径,windows中使用\\表示路径分隔符防止转义
'E:\\2019allstark\\practice1', #当前项目路径
'D:\\PyCharm 2019.1.1\\helpers\\pycharm_display',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\DLLs',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\lib', #部分内置模块,还有一些内置模块由C编写,看不到源码
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages', #第三方模块
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\win32\\lib',
'C:\\Users\\matt\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages\\Pythonwin',
'D:\\PyCharm 2019.1.1\\helpers\\pycharm_matplotlib_backend']
如果导入模块不在sys.path里面,可以用sys.path.append('你要导入的绝对路径')加入。
import sys, os print(os.path.dirname( os.path.abspath(__file__))) #获取当前文件目录或文件的绝对路径 sys.path.append(os.path.dirname( os.path.abspath(__file__)))
5. 包
包就是含有__init__文件的目录,导入包的本质就是执行包下的__init__文件。切记,包的查找路径包含当前目录和项目目录,项目目录一般定义为:base_path
注意事项:
- 凡是在导入时带点的,点的左边都必须是一个包,否则非法;
- 包A和包B下有同名模块也不会冲突,如A.a与B.a来自两个命名空间(不推荐)
绝对导入:
- 从项目目录或根目录开始导入;
- 绝对路径增删后修改繁琐
相对导入:
- 从当前目录导入(sys.path含有当前目录);使用 . 或者 .. 导入。符号 . 代表当前目录,..代表上一级目录,...代表上一级的上一级目录
- 本文件不能以脚本执行,只能以模块导入的方式执行
自定义导入:
执行文件使用绝对导入较繁琐,使用内置变量__file__构造项目目录,__file__返回当前文件路径
import os,sys print(__file__) ret = __file__.split('/') ret = ret[:-2] base_path= '/'.join(ret) # base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #(推荐此方法);os.path.dirname(),返回目录名;os.path.abspath()返回绝对路径; sys.path.append(base_path)
E:/2019allstark/practice1/path1/a1.py #file在pycharm返回绝对路径,在cmd返回相对路径
参考:__file__返回路径解析
https://www.cnblogs.com/jyfootprint/p/9429346.html
二 正则表达式
正则表达式(regular expression)描述了一种字符串匹配的模式(pattern)。
将正则表达式放到带匹配字符串从头到尾一一匹配。
1. 正则基础
1.1 字符组
在一个字符的位置上允许出现字符的组合,字符组表示的是一个字符的位置。
字符组 | 举例 | 说明 |
枚举 | [0123456] | 内部是or的关系 |
范围 | [1-9] | - 表示范围匹配 |
组合 | [1-9abcA-Z] | 只能检测 - 左右两边各一个字符,进而确定范围 |
1.2 元字符
简化字符组的写法
元字符 | 匹配内容 | 元字符 | 匹配内容 |
. | 除换行符(\n)以外的任意字符 | ^,\A | 开始 |
\d | 数字 | $,\Z | 结尾 |
\w | 数字、字符、下划线 | a|b | a或b(优先匹配a;a、b相似,a长) |
\s | 空格、\n、\t | () | |
\D | 非数字 | [...] | 字符组 |
\W | 非(数字、字符、下划线) | [^...] | 非 |
\S | 非(空格、\n、\t) | ||
\n | 换行符 | ||
\t | 制表符 | ||
\b | 边界(开始、结尾、空格) |
1.3 量词
量词只作用于前边一个元字符
量词 | 含义 |
* | 重复0次或多次 |
+ | 重复1次或多次 |
? | 出现0次或1次(可有可无) |
{n} | 重复n次 |
{n,} | 重复至少n次 |
{n,m} | 重复n到m次 |
贪婪匹配:匹配尽可能多的内容,程序默认,采用回溯算法;
惰性匹配:匹配尽可能少的内容,调用方法为在量词后边加一个问号?
2. 常用方法
2.1 re.finall(pattern, string)
以列表的形式返回匹配到的值
2.2 re.search(pattern, string);
以对象的形式返回匹配到值,只会匹配字符串第一个值,配合result.group()查看,匹配不到返回None
2.3 re.match(pattern, string)
完全等效于re.search(^str)
2.4 re.sub(pattern, repl, string, count=0)
相当于字符串的replace方法,返回值为修改后的字符串
2.5 re.sub(pattern, repl, string, count=0)
返回值是元组:(str,n),n表示替换的次数
2.6 re.split(pattern, string)
相当于字符串的split,返回值为列表
2.7 re.comfile(pattern)
将正则模式存储在result中,允许多次调用,节省时间
2.8 re.finditer()
将匹配结果存储在可迭代对象中,一般使用for循环调用
import re
print(re.findall('\d+', '123matt456logan'))
print(re.search('\d+','123matt456logan').group())
print(re.match('\d+','123matt456logan'))
print(re.sub('\d+','AAA','123matt456logan'))
print(re.subn('\d+','AAA','123matt456logan')) print(re.split('\d+','123matt456logan')) ret = re.compile('\d+') print(ret) print(ret.findall('123matt456logan')) print(re.finditer('\d+', '123matt456logan')) ['123', '456'] 123 AAAmattAAAlogan ('AAAmattAAAlogan', 2) ['', 'matt', 'logan'] #分割时会产生空字符 re.compile('\\d+') ['123', '456']
3. 分组
使用分组会产生诸多特性
3.1 re.findall()分组特性
分组部分优先显示,经常配合‘’或 |‘’用于优先显示
import re
print(re.findall('\d+\w', '123matt456Logan'))
print(re.findall('\d+(\w)', '123matt456Logan'))
print(re.findall('\d+(?:\.\d+)|\d+', '12-252+26-3*89/25-25.36*56+5.25'))
print(re.findall('\d+(?:\.\d+)|(\d+)', '12-252+26-3*89/25-25.36*56+5.25'))
['123m', '456L'] ['m', 'L'] ['12', '252', '26', '3', '89', '25', '25.36', '56', '5.25'] ['12', '252', '26', '3', '89', '25', '', '56', ''] #没显示部分为空白
3.2 re.search() 分组特性
实现括号的定位显示
print(re.search('\d+\w+', '123matt-456Logan'))
ret = re.search('\d+(\w)(\w)(\w)', '123matt-456Logan')
print(ret.group(0));print(ret.group(1));print(ret.group(2));print(ret.group(3)) #定位括号
123mat; m; a; t #result.group(int = 0)
3.3 re.split()分组特性
显示分割内容
print(re.split('\d+', '123matt-456Logan'))
print(re.split('(\d+)', '123matt-456Logan'))
['', 'matt-', 'Logan']
['', '123', 'matt-', '456', 'Logan']
3 4 分组命名
print(re.search('<\w+>\w+\w+>', 'abcdef
').group()) ret = re.search('<(?P\w+)>\w+(?P=id1)>', ' abcdef
') #分组关键字形式 print(ret.group()) #全部显示 print(ret.group(1)) # print(ret.group(2)) #报错,分组命名前后()表示一个 print(ret.group('id1')) #显示对应名称的分组()内容 res = re.search(r'<(?P\w+)>\w+<(/\1)>', ' abcdef
') #分组位置形式abcdef
abcdef
h1; h1
三 time模块
1. 时间形式
- timestamp:时间戳,从1970年1月1日00:00:00开始按秒计算,北京时间为从8时开始计算;
- struct_time:时间元组,共有九个元素组;
- format time :格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。
1.1 时间戳
生成函数:time.time()
print(time.time()) #1567067674.6788714,从1970年1月1日08:00:00计算的秒数
1.2 时间元组
伪生成函数:time.localtime(seconds=None);When 'seconds' is not passed in, convert the current time instead.
print(time.localtime()) #返回值为struct_time对象格式 print(time.localtime().tm_year) time.struct_time(tm_year=2019, tm_mon=8, tm_mday=29, tm_hour=18, tm_min=29, tm_sec=14, tm_wday=3, tm_yday=241, tm_isdst=0) 2019
属性 值 tm_year(年) 比如2017 tm_mon(月) 1 - 12 tm_mday(日) 1 - 31 tm_hour(时) 0 - 23 tm_min(分) 0 - 59 tm_sec(秒) 0 - 61 tm_wday(weekday) 0 - 6(0表示周日) tm_yday(一年中的第几天) 1 - 366 tm_isdst(是否是夏令时) 默认为-1
1.3 格式化字符串时间
伪生成函数:time.strftime(format,p_tuple=None);When the time tupleis not present, current time as returned by localtime() is used.
print(time.strftime('%Y-%m-%d %X')) 2019-08-29 18:09:27
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12) %M 分钟数(00=59) %S 秒(00-59) %a 本地简化星期名称 %A 本地完整星期名称 %b 本地简化的月份名称 %B 本地完整的月份名称 %c 本地相应的日期表示和时间表示 %j 年内的一天(001-366) %p 本地A.M.或P.M.的等价符 %U 一年中的星期数(00-53)星期天为星期的开始 %w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始 %x 本地相应的日期表示 %X 本地相应的时间表示 %Z 当前时区的名称 %% %号本身
2. 三种格式转化
1、time.localtim(seconds=None)
返回时间戳的struct_time格式;
2、time.mktime(p_tuple)
将struct_time格式转成时间戳;
3、time.strftime("%Y-%m-%d %H:%M:%S",p_tuple=None )
将struct_time格式转成指定的字符串格式
4、time.strptime("2016/05/22","%Y/%m/%d")
将日期字符串转成 struct_time格式
import time print(time.time()) print(time.localtime(1500000000)) print(time.strftime('%Y-%m-%d')) print(time.strptime('2019-08-30','%Y-%m-%d')) #'%Y-%m-%d'为'2019-08-30'的识别模式 1567076841.7220666 time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0) 2019-08-29 time.struct_time(tm_year=2019, tm_mon=8, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=242, tm_isdst=-1)
时间差练习:只有时间戳能加减
import time true_time=time.mktime(time.strptime('2018-09-11 08:30:00','%Y-%m-%d %H:%M:%S')) time_now=time.time() dif_time=time_now-true_time struct_time=time.gmtime(dif_time) print('过去了%d年%d月%d天%d小时%d分钟%d秒'%(struct_time.tm_year-1970,struct_time.tm_mon-1, struct_time.tm_mday-1,struct_time.tm_hour, struct_time.tm_min,struct_time.tm_sec))
过去了0年11月18天10小时42分钟25秒
3. 固定格式转化
5、time.ctime(second=None)
转化为C格式字符串
6、time.asctime(p_tuple=None)
与time.strftime类似,转化为C格式字符串
import time print(time.ctime()) print(time.asctime()) Thu Aug 29 19:21:33 2019 #西方习惯的格式 Thu Aug 29 19:21:33 2019
四 datetime模块
datetime模块封装了time模块,提供更多接口,内部的类有:date,time,datetime,timedelta,tzinfo。
1. date类
def __init__(self, year: int, month: int, day: int),提供日期的操作
1、obj = date(2017,8,8)
初始化函数,创建date类型的对象
2、date.today()
返回当前本地日期
3、date.fromtimestamp(timestamp)
返回时间戳的日期
4、date.strftime(format)
返回自定义格式的时间字符串
5、replace(year, month, day):
生成一个新的date对象,指定参数替换
2. time类
def __init__(self, hour, minute, second, microsecond, tzinfo)
6、datetime.time()
初始化函数
7、time_obj. hour/min/sec/micsec()
返回小时/分钟/秒/毫秒
8、time_obj. isoformat()
返回型如"HH:MM:SS"格式的字符串表示
3. datetime类
封装time模块
4. timedelta类
9、timedelta(days,hours,minutes,second,microseconds,weeks)
初始化函数
10、timedelta_obj. days/secons/microseconds()
返回天数、秒、毫秒,没有小时,分钟
加减操作
- datetime_obj = datetime_obj +/- timedelta_obj
- timedelta_obj = datetime_obj - datetime_obj
date与datetime对象都可进行加减操作
import datetime t1 = datetime.datetime.now() delta = datetime.timedelta(weeks=1) #默认为days=1 print(t1 + delta) t3 = datetime.datetime(2019, 12, 26, 10, 10, 10) print(t3 - t1);print((t3 - t1).days) 2019-09-06 12:44:34.275388 117 days, 21:25:35.724612; 117
参考:datetime模块详解
https://www.cnblogs.com/xtsec/p/6682052.html
五 random模块
1. 整数
1、random.randint(1,6) 随机生成指定范围 [a,b] 的整数
2、rangdom.randrange(1,100,2) 随机生成指定范围 [a,b] 的整数,步长为2
2. 浮点数
3、random.random() 随机生成指定范围 [0,1) 的浮点数
4、random.uniform(a,b) 随机生成指定范围 [a,1) 的浮点数
源码 a + (b-a) * self.random()
3. 抽取
5、random.choice(seq) 随机抽取元素
Some built-in sequence types are list, str, tuple and bytes
6、random.sample(Population,k) 随机抽取k个元素
Population must be a sequence or set. For dicts, use list(d)
4. 打乱
7、random.shuffle(list) 随机打乱顺序
return None
#随机验证码实例
import random check_code = '' for i in range(4): cur = random.randrange(0,4) #随机猜的范围,与循环次数相等 #字母 if cur == i: tmp = chr(random.randint(65,90)) #数字 else: tmp = random.randint(0,9) #randint包含最后一位 check_code += str(tmp) print(check_code)
六 os模块
1 基本方法
os模块是与操作系统交互的一个接口
# 当前执行这个python文件的工作目录相关的工作路径
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径;与(__file__)返回的文件路径不相同
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
# 和目录相关
os.makedirs(name,exit_ok=False) 可生成多层递归目录,最底层目录存在时报错;
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印,不向下二级递归搜索
# 和文件相关
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息,返回对象
# 和操作系统差异相关
# os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
# os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
# os.pathsep 输出用于分割文件路径的字符串,在环境变量中; win下为;,Linux下为:
# os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
# 和执行系统命令相关
os.system("bash command") 运行shell命令,直接显示,不能保存结果
os.popen("bash command).read() 运行shell命令,获取执行结果;返回对象,以read()打开
os.environ 获取系统环境变量
# path系列,和路径相关
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录;os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如果path以/或\结尾,那么就会返回空值,即os.path.split(path)的第二个元素。
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略;自动添加分隔符
os.path.getatime(path) 返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回文件的大小
os.urandom(int) 返回int位的bytes
os.getpid() 返回进程的号
os.getppid() 返回父进程号
os.stat('path/filename') 获取文件/目录信息 的结构说明
stat 结构: st_mode: inode 保护模式 st_ino: inode 节点号。 st_dev: inode 驻留的设备。 st_nlink: inode 的链接数。 st_uid: 所有者的用户ID。 st_gid: 所有者的组ID。 st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
2. 获取文件夹大小
os.walk() 方法用于通过在目录树中游走输出在目录中的文件名,向下递归。
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
-
top -- 是你所要遍历的目录的地址, 返回值是一个三元组(root,dirs,files)。
- root 所指的是当前正在遍历的这个文件夹的本身的地址
- dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
- files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
-
topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。
-
onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
-
followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。
import os def getdirsize(dir): size = 0 for root, dirs, files in os.walk(dir): size += sum([os.path.getsize(os.path.join(root, name)) for name in files]) #生成列表再相加 return size if __name__ == '__main__': size = getdirsize(os.getcwd()) print('There are %.3f Mb' %(size/1024/1024)) #保留小数的位数
七 sys模块
与python解释器交互的命令
sys.argv 命令行参数List,第一个元素是程序本身路径,例如cmd中输入mysql -uroot -ppwd;sys.argv[0]='mysql'; sys.argv[1]='-uroot'; sys.argv[2]='-ppwd' sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
八 json & picle模块
json 和 pickal模块都只有四个方法: dumps、dump、loads、load
1. json四种方法
JSON (JavaScript Object Notation)是一种使用广泛的轻量数据格式,主要用于数据交互。json和js对象格式一样,字符串中的属性名必须加双引号其他得和js语法一致。
json生成的数据存在于内存,需要write和read进行存储和读取。
JSON和Python之间的数据转换对应关系如下表:(不支持set)
JSON | Python |
---|---|
object | dict |
array | list、tuple |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
json方法大致分为:
- 网络传输:dumps、loads
- 文件读写:dump、load
1.1 dumps(obj)、dump(obj,fp)
用于将 Python 对象编码成 JSON 字符串
1.2 loads(obj)、load(fp)
用于解码 JSON 数据;返回 Python 字段的数据类型
import json dic = {'a': 1, 'b': 2} dic_json = json.dumps(dic) print([dic_json]) #print([ ])加上[]为真实打印,附带数据类型 dic_new = json.loads(dic_json) print([dic_new]) with open('file', 'w')as f: json.dump(dic, f) with open('file')as f2: aaa = json.load(f2) print([aaa])
['{"a": 1, "b": 2}'];[{'a': 1, 'b': 2}];[{'a': 1, 'b': 2}]
1.3 格式化显示
import json data = {'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16} #针对字典类型 json_dic2 = json.dumps(data, sort_keys=True, indent=2, separators=(',', ':'), ensure_ascii=False) #ensure_asscii = True显示Unicode编码,不显示汉字 print(json_dic2) { "age":16, "sex":"male", "username":[ "李华", "二愣子" ] }
2. json限制
2.1 json转化字典时, keys must be str, int, float, bool or None
key不接受元组,且数字必须字符串化
元组在做value时,会被转换为list
2.2 双引号
json生成和导入字符串时必须是双引号
2.3 文件允许多次dump,不允许多次load
import json dic1 = {1: 'a', 2: 'b'} dic2 = {'c': 3, 'd': 4} with open('file', 'w') as f: # json.dump(dic1, f) 形成数据黏连,在一行中 # json.dump(dic2, f) ret1 = json.dumps(dic1) ret2 = json.dumps(dic2) f.write(ret1 + '\n') f.write(ret2 + '\n') with open('file') as f2: # json.load(f2) 不允许读取多个数据 for line in f2: ret = json.loads(line) print(ret)
{'1': 'a', '2': 'b'};{'c': 3, 'd': 4}
3. pickle特性
pickle模块是将Python所有的数据结构以及对象等转化成bytes类型,然后还可以反序列化还原回去。pickle都是bytes类型
json模块序列化出来的是通用格式,其它编程语言都认识,就是普通的字符串;pickle模块序列化出来的只有python可以认识,其他编程语言表现为乱码
pickle可以序列化函数;反序列化时,读取文件中需要有该函数的定义(定义和参数必须相同,内容可以不同)
pickle方法:
- 传输:loads(obj)、dumps(obj)
- 文件操作:load(fp)、dump(obj,fp)
3.1 pickle支持几乎所有数据类型
3.2 pickle支持序列化自定义对象和函数
3.2 pickle支持多次存储和读取
import pickle def func(): #反序列化时必须在 print('aaa') class Student: def __init__(self, name, age): #反序列化时必须在 self.name = name self.age = age s1 = Student('matt', 20) with open('file', 'wb') as f: #每次写入会有标识,二进制形式写入 pickle.dump(func, f) pickle.dump(s1, f) with open('file', 'rb') as f2: while True: try: #多次读取的格式,多次写入就多少次读取,不能一次读取 print(pickle.load(f2)) except EOFError: break<__main__.Student object at 0x00000000027D8E48>
参考:json详细解析
https://www.jb51.net/article/139498.htm
九 hashlib模块
1. 模块介绍
此模块通过一个函数,把任意长度的数据转换为一个固定长度的数据串,又称为摘要算法,加密算法,哈希算法,散列算法等等,算法有md5, sha1, sha224, sha256, sha384, sha512。
md5是常用的算法,主要是速度快。
import hashlib md5 = hashlib.md5() #创建md5对象 md5.update('how to use md5 in python hashlib?'.encode()) md5.update(b'haha') #update的数据必须是bytes print(md5.hexdigest())
#文件读取 def file_check(file_path): with open(file_path,mode='rb') as f1: sha256 = hashlib.sha256() while 1: content = f1.read(1024) if content: sha256.update(content) else: return sha256.hexdigest()
2. hmac
基本与hashlib用法一致,在加salt时方便一点
import hmac message = b'Hello, world!' key = b'secret' h = hmac.new(key, message, digestmod='MD5') # 如果消息很长,可以多次调用h.update(msg) print(h.hexdigest())
十 logging模块
logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:
- 可以通过设置不同的日志等级,只输出重要信息,而不必显示大量的调试信息;
- print将所有信息都输出到标准输出中(screen);logging则可以设置信息输出的文件和格式;
1. 函数式配置
该方法简单,但定制型差:只能屏幕或文件输出一种、没有encode()选项,文件显示中文乱码
import logging logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', filename='file' #没有改语句时、屏幕显示,没有encoding选项 level=logging.ERROR #输出等级,一般都是INFO等级 ) logging.error('你好')
2019-08-31 11:45:03 AM - root - ERROR -test100: ��� #文件输出中文乱码
logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。 filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。 format:指定handler使用的日志显示格式。 datefmt:指定日期时间格式。 level:设置rootlogger(后边会讲解具体概念)的日志级别 #level = logging.DEBUG stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。 handles:
没有encoding选项,只能以ANSI(本地字符编码)输出
format参数中可能用到的格式化串: %(name)s Logger的名字 %(levelno)s 数字形式的日志级别 %(levelname)s 文本形式的日志级别 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有 %(filename)s 调用日志输出函数的模块的文件名 %(module)s 调用日志输出函数的模块名 %(funcName)s 调用日志输出函数的函数名 %(lineno)d 调用日志输出函数的语句所在的代码行 %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示 %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数 %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 %(thread)d 线程ID。可能没有 %(threadName)s 线程名。可能没有 %(process)d 进程ID。可能没有 %(message)s用户输出的消息
输出等级
FATAL:致命错误
CRITICAL:50,特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:40,发生错误时,如IO操作失败或者连接问题
WARNING:30,发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:20,处理请求或者状态变化等日常事务
DEBUG:10,调试过程中使用DEBUG等级,如算法中每个循环的中间状态
2. 对象配置
import logging logger = logging.getLogger() #1、创建一个logger对象 fh = logging.FileHandler('file_name',encoding='utf-8') #2、创建一个文件管理操作符 #函数配置没有encoding选项 sh = logging.StreamHandler() #3、创建一个屏幕管理操作符 #4、创建一个日志输出的格式 fm1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG) #5、设置输出等级 fh.setFormatter(fm1) #6、文件管理操作符绑定一个格式 sh.setFormatter(fm1) #7、屏幕管理操作符绑定一个格式 logger.addHandler(fh) #8、logger对象绑定文件管理操作符 logger.addHandler(sh) #9、logger对象绑定屏幕管理操作符 logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message') #屏幕和文件同时输出
参考:logging模块解析
https://www.cnblogs.com/liujiacai/p/7804848.html
十一 异常处理
1. 异常基础
常见的异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
2. 异常处理语句
发生异常后,会执行exit(),直接退出程序
异常处理只能处理指定、有限的异常,因为异常类的数量是一定的。
2.1 try/except
基础语法,最常用
try: a = [1, 2] b = a[5] #发生异常 except (ValueError,IndexError) as e: #多状况,发生任何一种都触发 print(e) print('aaa') #发生错误,能够执行
list index out of range;aaa
发生错误后只是try中的程序不再执行,而执行except中的语句,之后再执行主程序。即使发生错误,下端的主程序也能执行。
2.2 try/except/else
类似于for/else语句:for正常走完能执行else语句,若for内部有break,则不执行else语句
try: a = [1, 2] b = a[1] except IndexError as e: print(e) else: #未发生错误,执行else,发生错误,不执行else print('aaa') print('bbb')
aaa;bbb
2.3 try/except(/excepy)/finally
不管是否发生错误,都会执行finally语句,比下端主程序更安全
try: a = [1, 2] b = a[3] except IndexError as e:print(e) else:print('aaa') finally:print('bbb')
aaa;bbb
3. Exception
万能异常,Exception包含了所有的异常类
try: a = [1, 2] b = a[3] except Exception as e: #不用指定异常类的类名,方便一些,但一定打印信息 print(e)
4. raise
主动抛出异常,能改写异常类的具体信息
try: a = [1, 2] b = a[3] # raise ValueError('aaa') #这样抛出异常会打印aaa except Exception as e: print(e) raise #源码中常见,原封不动抛出异常
list index out of range
Traceback (most recent call last):
File "E:/2019allstark/soft/core/test100.py", line 3, in
b = a[3]
IndexError: list index out of range
5. 自定义异常
class EvaException(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg try: raise EvaException('类型错误') except EvaException as e: print(e)
6. assert
源码中个经常出现,assert只有True和False,主要判断源码中继续执行的条件是否准备好。
assert True #ture继续往下走 print('aaa') assert 0 #false报错 print('bbb')
aaa
Traceback (most recent call last):
File "E:/2019allstark/soft/core/test100.py", line 3, in
assert 0
AssertionError