logging模块
我们来说一下这个logging模块,这个模块的功能是记录我们软件的各种状态,你们现在和我一起找到红蜘蛛的那个图标,然后右键找一找是不是有个错误日志.其实每个软件都是有错误日志的,开发人员可以通过错误日志中的内容
对他的程序进行修改
我们先来看一下函数式简单配置
import logging
logging.debug(
'debug message'
)
logging.info(
'info message'
)
logging.warning(
'warning message'
)
logging.error(
'error message'
)
logging.critical(
'critical message'
)
默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息。
我们自己用函数写的这个可以正常使用但是不够灵活,我们看看这个灵活的
灵活配置日志级别,日志格式,输出位置:
import logging
logging.basicConfig(level=logging.DEBUG,
format=
'%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s'
,
datefmt=
'%a, %d %b %Y %H:%M:%S'
,
filename=
'/tmp/test.log'
,
filemode=
'w'
)
logging.debug(
'debug message'
)
logging.info(
'info message'
)
logging.warning(
'warning message'
)
logging.error(
'error message'
)
logging.critical(
'critical message'
)
logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
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用户输出的消息
logger对象配置
import logging
logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler(
'test.log'
,encoding=
'utf-8'
)
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh) #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
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'
)
ogging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过
fh.setLevel(logging.Debug)单对文件流设置某个级别。
序列化
我们今天学习下序列化,什么是序列化呢? 将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。
为什么要有序列化模块: 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。 但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。 你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢? 没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串, 但是你要怎么把一个字符串转换成字典呢? 聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。 eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。 BUT!强大的函数有代价。安全性是其最大的缺点。 想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。 而使用eval就要担这个风险。 所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
序列化的目的
1、以某种存储形式使自定义对象持久化; 2、将对象从一个地方传递到另一个地方。 3、使程序更具维护性。
json
Json模块提供了四个功能:dumps、dump、loads、load
dumps 及 loads
import json
dic = {
'k1'
:
'v1'
,
'k2'
:
'v2'
,
'k3'
:
'v3'
}
str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic) #<
class
'str'
> {
"k3"
:
"v3"
,
"k1"
:
"v1"
,
"k2"
:
"v2"
}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的
dic2 = json.loads(str_dic) #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2) #<
class
'dict'
> {
'k1'
:
'v1'
,
'k2'
:
'v2'
,
'k3'
:
'v3'
}
list_dic = [1,[
'a'
,
'b'
,
'c'
],3,{
'k1'
:
'v1'
,
'k2'
:
'v2'
}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型
print(type(str_dic),str_dic) #<
class
'str'
> [1, [
"a"
,
"b"
,
"c"
], 3, {
"k1"
:
"v1"
,
"k2"
:
"v2"
}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<
class
'list'
> [1, [
'a'
,
'b'
,
'c'
], 3, {
'k1'
:
'v1'
,
'k2'
:
'v2'
}]
dump 及 load
import json
f = open(
'json_file'
,
'w'
)
dic = {
'k1'
:
'v1'
,
'k2'
:
'v2'
,
'k3'
:
'v3'
}
json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()
f = open(
'json_file'
)
dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)
其他参数说明
Serialize obj to a JSON formatted str.(字符串表示的json对象) Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse). If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity). indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. sort_keys:将数据根据keys的值进行排序。 To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.
json格式化输出
import json
data = {
'username'
:[
'李华'
,
'二愣子'
],
'sex'
:
'male'
,
'age'
:16}
json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(
','
,
':'
),ensure_ascii=False)
print(json_dic2)
pickle模块
用于序列化的两个模块
json,用于字符串 和 python数据类型间进行转换 pickle,用于python特有的类型 和 python的数据类型间进行转换 pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)pickle是python特有的模块.
import pickle
dic = {
'k1'
:
'v1'
,
'k2'
:
'v2'
,
'k3'
:
'v3'
}
str_dic = pickle.dumps(dic)
print(str_dic) #一串二进制内容
dic2 = pickle.loads(str_dic)
print(dic2) #字典
import time
struct_time = time.localtime(1000000000)
print(struct_time)
f = open(
'pickle_file'
,
'wb'
)
pickle.dump(struct_time,f)
f.close()
f = open(
'pickle_file'
,
'rb'
)
struct_time2 = pickle.load(f)
print(struct_time2.tm_year)
这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢? 这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。 如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。 但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~ 所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块 但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle
总结:
json模块里的dumps是将python的数据结构转换成字符串,loads是将字符串类型转换成python的数据结构
json模块里的dump是将python的数据结构转换成字符串,然后存入到文件当中
json模块里的load是将文件中字符串类型转换成python的数据结构
pickle模块里的dumps是将python的数据结构转换成二进制的文件,loads是将二进制的文件转换成python的
数据结构
pickle模块里的dump是将python的数据结构转换成二进制然后存入到文件中
pickle模块里的load是将文件中的二进制文件转成python的数据结构
random 模块
random是一个随机数模块,我们一般用来生成一些没有规则的内容
获取0-1之间的随机小数
import random
print(random.random())
生成指定的数字内的随机小数怎么办??
import random
print(random.uniform(1,5))
整数怎么做到随机呢
import random
print(random.randint(1,5))
生成随机的奇数和偶数
import random
print(random.randrange(1,5,2)) #随机生成1-5的奇数
print(random.randrange(0,5,2)) #随机生成0-5的偶数
现在有一个列表 lst = ['张开','宝元','佩奇','太白'],随机抽一个人出来
import random
lst = [
'张开'
,
'宝元'
,
'佩奇'
,
'太白'
]
print(random.choice(lst))
随机抽出两个来
import random
lst = [
'张开'
,
'宝元'
,
'佩奇'
,
'太白'
]
print(random.choices(lst,k=2))
随机出来的两个内容是有重复的,没有满足需求重新实现
import random
lst = [
'张开'
,
'宝元'
,
'佩奇'
,
'太白'
]
print(random.sample(lst,k=2))
给你一个列表你给我让他变成随机排序的
import random
lst = [1,2,3,4,5,6]
random.shuffle(lst)
print(lst)