一,什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
为何要使用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
二,序列化模块。
什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化.
1 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 2 现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。 3 但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。 4 你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢? 5 没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串, 6 但是你要怎么把一个字符串转换成字典呢? 7 聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。 8 eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。 9 BUT!强大的函数有代价。安全性是其最大的缺点。 10 想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。 11 而使用eval就要担这个风险。 12 所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构) 13 14 为什么要有序列化模块
序列化的目的
2.1 json模块
Json模块提供了四个功能:dumps、dump、loads、load
1 import json 2 dic = {'k1':'v1','k2':'v2','k3':'v3'} 3 str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串 4 print(type(str_dic),str_dic) #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"} 5 #注意,json转换完的字符串类型的字典中的字符串是由""表示的 6 7 dic2 = json.loads(str_dic) #反序列化:将一个字符串格式的字典转换成一个字典 8 #注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示 9 print(type(dic2),dic2) #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} 10 11 12 list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}] 13 str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型 14 print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}] 15 list_dic2 = json.loads(str_dic) 16 print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}] 17 18 loads和dumps 19 20 dumps loads
1 import json 2 f = open('json_file','w') 3 dic = {'k1':'v1','k2':'v2','k3':'v3'} 4 json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件 5 f.close() 6 7 f = open('json_file') 8 dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回 9 f.close() 10 print(type(dic2),dic2) 11 12 dump load
1 Serialize obj to a JSON formatted str.(字符串表示的json对象) 2 Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key 3 ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) 4 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). 5 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). 6 indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json 7 separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 8 default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. 9 sort_keys:将数据根据keys的值进行排序。 10 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. 11 12 其他参数说明
1 import json 2 data = {'username':['李华','二愣子'],'sex':'male','age':16} 3 json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False) 4 print(json_dic2)
2.2 pickle模块
用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)
1 import pickle 2 dic = {'k1':'v1','k2':'v2','k3':'v3'} 3 str_dic = pickle.dumps(dic) 4 print(str_dic) #一串二进制内容 5 6 dic2 = pickle.loads(str_dic) 7 print(dic2) #字典 8 9 import time 10 struct_time = time.localtime(1000000000) 11 print(struct_time) 12 f = open('pickle_file','wb') 13 pickle.dump(struct_time,f) 14 f.close() 15 16 f = open('pickle_file','rb') 17 struct_time2 = pickle.load(f) 18 print(struct_time2.tm_year) 19 20 pickle
这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢?
这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。
如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块
但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle
2.3 shelve模块
shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。
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)
这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
import shelve f = shelve.open('shelve_file', flag='r') existing = f['key'] f.close() print(existing)
由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
1 import shelve 2 f1 = shelve.open('shelve_file') 3 print(f1['key']) 4 f1['key']['new_value'] = 'this was not here before' 5 f1.close() 6 7 f2 = shelve.open('shelve_file', writeback=True) 8 print(f2['key']) 9 f2['key']['new_value'] = 'this was not here before' 10 f2.close() 11 12 设置writeback
writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。
三,hashlib模块
算法介绍
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
1 import hashlib 2 3 md5 = hashlib.md5() 4 md5.update('how to use md5 in python hashlib?') 5 print md5.hexdigest() 6 7 计算结果如下: 8 d26a53750bc40b38b65a520292f69306
如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。
四,configparser模块
该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值)。
1 """ 2 Django settings for webwx project. 3 4 Generated by 'django-admin startproject' using Django 1.10.3. 5 6 For more information on this file, see 7 https://docs.djangoproject.com/en/1.10/topics/settings/ 8 9 For the full list of settings and their values, see 10 https://docs.djangoproject.com/en/1.10/ref/settings/ 11 """ 12 13 import os 14 15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 18 19 # Quick-start development settings - unsuitable for production 20 # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 21 22 # SECURITY WARNING: keep the secret key used in production secret! 23 SECRET_KEY = 'mpn^n-s-&+ckg_)gl4sp^@8=89us&@*^r1c_81#x-5+$)rf8=3' 24 25 # SECURITY WARNING: don't run with debug turned on in production! 26 DEBUG = True 27 28 ALLOWED_HOSTS = [] 29 30 31 # Application definition 32 33 INSTALLED_APPS = [ 34 'django.contrib.admin', 35 'django.contrib.auth', 36 'django.contrib.contenttypes', 37 'django.contrib.sessions', 38 'django.contrib.messages', 39 'django.contrib.staticfiles', 40 'web', 41 ] 42 43 MIDDLEWARE = [ 44 'django.middleware.security.SecurityMiddleware', 45 'django.contrib.sessions.middleware.SessionMiddleware', 46 'django.middleware.common.CommonMiddleware', 47 # 'django.middleware.csrf.CsrfViewMiddleware', 48 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 'django.contrib.messages.middleware.MessageMiddleware', 50 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 ] 52 53 ROOT_URLCONF = 'webwx.urls' 54 55 TEMPLATES = [ 56 { 57 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 'DIRS': [os.path.join(BASE_DIR, 'templates')] 59 , 60 'APP_DIRS': True, 61 'OPTIONS': { 62 'context_processors': [ 63 'django.template.context_processors.debug', 64 'django.template.context_processors.request', 65 'django.contrib.auth.context_processors.auth', 66 'django.contrib.messages.context_processors.messages', 67 ], 68 }, 69 }, 70 ] 71 72 WSGI_APPLICATION = 'webwx.wsgi.application' 73 74 75 # Database 76 # https://docs.djangoproject.com/en/1.10/ref/settings/#databases 77 78 DATABASES = { 79 'default': { 80 'ENGINE': 'django.db.backends.sqlite3', 81 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 82 } 83 } 84 85 86 # Password validation 87 # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 88 89 AUTH_PASSWORD_VALIDATORS = [ 90 { 91 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 92 }, 93 { 94 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 95 }, 96 { 97 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 98 }, 99 { 100 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 101 }, 102 ] 103 104 105 # Internationalization 106 # https://docs.djangoproject.com/en/1.10/topics/i18n/ 107 108 LANGUAGE_CODE = 'en-us' 109 110 TIME_ZONE = 'UTC' 111 112 USE_I18N = True 113 114 USE_L10N = True 115 116 USE_TZ = True 117 118 119 # Static files (CSS, JavaScript, Images) 120 # https://docs.djangoproject.com/en/1.10/howto/static-files/ 121 122 STATIC_URL = '/static/' 123 STATICFILES_DIRS = ( 124 os.path.join(BASE_DIR,'static'), 125 ) 126 127 Django的配置文件举例
五,logging模块
1 import logging 2 logging.debug('debug message') 3 logging.info('info message') 4 logging.warning('warning message') 5 logging.error('error message') 6 logging.critical('critical message')
默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息。
灵活配置日志级别,日志格式,输出位置:
1 logging 日志 2 记录.花钱的,(淘宝)败家的, 3 访问的记录, 4 员工信息,debug等等都需要日志. 5 6 1,被动触发: 与异常处理配合.访问记录. 7 2, 主动触发:检测运维人员输入的指令,检测服务器的重要信息,访问记录.等等. 8 9 低配版 low版 10 import logging 11 logging.basicConfig(level=logging.INFO, 12 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', 13 filename='low版logging.log' 14 ) 15 msg = 'cpu 正常,硬盘参数...,流量的max:..最小值:.....' 16 logging.info(msg) 17 日志的信息:不能写入文件与显示 同时进行.
1 高配版 2 第一版:只输入文件中. 3 import logging 4 logger = logging.getLogger() # 创建logger对象. 5 fh = logging.FileHandler('高配版logging.log',encoding='utf-8') # 创建文件句柄
1 # 吸星大法 2 logger.addHandler(fh) 3 4 logging.debug('debug message') 5 logging.info('info message') 6 logging.warning('warning message') 7 logging.error('error message') 8 logging.critical('critical message')
1 # 第二版:文件和屏幕都存在. 2 import logging 3 logger = logging.getLogger() # 创建logger对象. 4 fh = logging.FileHandler('高配版logging.log',encoding='utf-8') # 创建文件句柄 5 sh = logging.StreamHandler() #产生了一个屏幕句柄
1 # 吸星大法 2 logger.addHandler(fh) #添加文件句柄 3 logger.addHandler(sh) #添加屏幕句柄 4 5 6 logging.debug('debug message') 7 logging.info('info message') 8 logging.warning('warning message') 9 logging.error('error message') 10 logging.critical('critical message')
1 # 第三版:文件和屏幕都存在的基础上 设置显示格式. 2 import logging 3 logger = logging.getLogger() # 创建logger对象. 4 fh = logging.FileHandler('高配版logging.log',encoding='utf-8') # 创建文件句柄 5 sh = logging.StreamHandler() #产生了一个屏幕句柄 6 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
1 # # 吸星大法 2 logger.addHandler(fh) #添加文件句柄 3 logger.addHandler(sh) #添加屏幕句柄 4 sh.setFormatter(formatter) # 设置屏幕格式 5 fh.setFormatter(formatter) # 设置文件的格式 (这两个按照需求可以单独设置) 6 7 8 logging.debug('debug message') 9 logging.info('info message') 10 logging.warning('warning message') 11 logging.error('error message') 12 logging.critical('critical message') 13 14 #第四版 文件和屏幕都存在的基础上 设置显示格式.并且设置日志水平. 15 import logging 16 logger = logging.getLogger() # 创建logger对象. 17 fh = logging.FileHandler('高配版logging.log',encoding='utf-8') # 创建文件句柄 18 sh = logging.StreamHandler() #产生了一个屏幕句柄 19 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 20 # logger.setLevel(logging.DEBUG) 21 #如果你对logger对象设置日志等级.那么文件和屏幕都设置了. 22 #总开关 默认从warning开始,如果想设置分开关:必须要从他更高级:(ERROR,critical)从这来个开始. 23 24 # # 吸星大法 25 logger.addHandler(fh) #添加文件句柄 26 logger.addHandler(sh) #添加屏幕句柄 27 sh.setFormatter(formatter) # 设置屏幕格式 28 fh.setFormatter(formatter) # 设置文件的格式 (这两个按照需求可以单独设置) 29 fh.setLevel(logging.DEBUG) 30 31 logging.debug('debug message') 32 logging.info('info message') 33 logging.warning('warning message') 34 logging.error('error message') 35 logging.critical('critical message')