一,module模块和包的介绍

1,在Python中,一个.py文件就称之为一个模块(Module)。

2,使用模块的好处?

最大的好处是大大提高了代码的可维护性

其次,编写代码不必从零开始,我们编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块

另外,使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,不必考虑名字会与其他模块冲突。但是也要尽量不与内置函数名字冲突。

3,种类

1)python标准库

2)第三方模块

3)自定义模块

4,文件夹和包的区别是,包里面有__init__.py文件。包可以用来组织有关系的一组文件,放在不同包里还可以避免模块名字冲突

5,使用import导入模块

1)例子

cal.py文件

print("ok1")
def add(x,y):
return x+y def sub(x,y):
return x-y
print("ok2")

main.py文件

import cal
print(cal.add(3,7))

执行main.py文件输出

ok1
ok2
10

说明import一个文件,首先会执行里面的代码。但是一般我们在cal.py里面定义功能性代码,执行放到一个文件里面

2)作用

a,执行里面的代码

b,导入变量名:cal

3)导入多个模块import module1,module2,module3

4)加入from语句作用,导入具体函数可以不使用cal.add(3,7)形式,而直接使用add(3,7)

from cal import add

print(add(3,7))

from module1 import *代表导入所有函数,但是这种方法不推荐。不推荐的理由在于,这样使用会导入一些自己不知道的函数名,如果在调用文件里自己起了重名函数,具体调用哪个将取决于from module1 import *和定义同名函数的相对位置。

使用from语句后,虽然可以导入某个具体函数,但是该py文件也和上面一样会全部执行

5)路径

运行某个py文件,会自动把其路径加入到sys.path里面,这样在这个路径下面的文件都可以使用import找到。而sys.path还包含一些python库的路径等等。有个需要注意的地方是Pycharm还会在sys.path里面添加工程文件的路径,更方便使用吧。

需要注意的是上面提到的路径只是执行文件的路径,如果导入的文件在其下一层,则需要把下一层的文件夹(或者包)加入到import语句中来。举个例子:目录结构如下,这里面my_module是一个文件夹

bin.py

my_module--cal.py

--main.py

在bin.py导入main.py使用的是这样的语句:from my_module import main

在main.py导入cal.py应该使用的是这样的语句:from my_module import cal,这里面虽然main.py和cal.py同级,但是直接用import cal会报错,因为系统只认bin.py(执行文件)所在的路径,而不管main.py和cal.py是否同级

多级路径情况下,使用点.来表示层级,举例:

bin.py--

web--web1--web3--__init.py

--cal.py

from web.web1.web3 import cal
from web.web1.web3.cal import add #可以直接使用add(2,6)

错误示例:

from web.web1 import web3   #执行web3的__init__文件,
print(web3.cal.add(2,6)) #执行会报错,唯一不支持的调用方式

解决上面错误示例的方法:在web3文件夹的__init__.py里面加入

from . import cal

则会正确执行 web3.cal.add(2,6)

提示:如果我们的自定义模块和Python里的模块重名,由于在sys.path里面我们执行文件的路径在前,Python库的路径在后,首先会搜索执行文件的路径,这样就会把自定义模块导入而不会继续向后搜索系统模块。

修改路径的方法和实效

临时修改:

import sys
sys.path.append()

永久修改:

windows:系统属性--高级--环境变量--系统变量--Path

在工程上的实际应用中目录结构如下,一般bin是执行的起点:

fatherdir--bin--bin.py

--my_module--main.py

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) #通过BASE_DIR得到整个项目根目录。可以适应拷贝到其他机器运行的情况,但目录结构仅限往上一层的情况

6,相关知识点:__name__系统变量,取值依据其在不同的文件里而定

1,在执行文件其值为字符串:__main__

2,在被调用文件其值为:该文件的路径,例如:web.web1.web3.cal

使用方法 if __name__=='__main__'

1,在调用文件里使用,后面是测试代码。这样被其他文件调用的时候这些测试代码不会执行。

2,在执行文件里使用,就是不想让这个文件成为其他文件调用的对象。比如这种情况,这个执行文件里的函数需要被其他人调用,其他人引用这个文件,使用其中某个具体的函数。如果没有这句话,则会把不需要执行的部分也执行一遍。

二,Python内置模块

(一)time模块

import time

#时间戳,从1970年UNIX诞生到现在的秒数,做计算使用
print(time.time()) #1481321748.481654秒
#输出:1549155273.7783637 #当前时间戳的结构化时间---当地时间
print(time.localtime(1549152782))
#输出:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=3, tm_hour=8, tm_min=13, tm_sec=2, tm_wday=6, tm_yday=34, tm_isdst=0)
t=time.localtime()
print(t.tm_year)
#输出:2019
print(t.tm_wday)
#输出:6
#当前时间戳的结构化时间---UTC格林尼治
print(time.gmtime())
#输出:time.struct_time(tm_year=2019, tm_mon=2, tm_mday=3, tm_hour=0, tm_min=54, tm_sec=33, tm_wday=6, tm_yday=34, tm_isdst=0) #结构化时间转换成时间戳
print(time.mktime(time.localtime()))
#输出:1549155273.0 #结构化时间转成字符串时间strftime
print(time.strftime('%Y---%m-%d %X',time.localtime()))
#输出:2019---02-03 08:54:33
#字符串时间转成结构化时间strptime
print(time.strptime("2016:12:24:17:50:36","%Y:%m:%d:%X"))
#输出:time.struct_time(tm_year=2016, tm_mon=12, tm_mday=24, tm_hour=17, tm_min=50, tm_sec=36, tm_wday=5, tm_yday=359, tm_isdst=-1) #省事的方法直接使用asctime和ctime,但是格式是固定的,如:Sun Feb 3 08:48:31 2019
print(time.asctime())#asctime是从结构化时间转换成格式化字符串
#输出:Sun Feb 3 08:54:33 2019
print(time.ctime()) #ctime是从时间戳转换成格式化字符串
#输出:Sun Feb 3 08:54:33 2019 #线程推迟指定时间运行,单位:秒
time.sleep(1) #clock() 时间差 #另外一个时间模块datetime,看起来更直观一点
import datetime
print(datetime.datetime.now())
#输出:2019-02-03 08:54:34.882426

(二)random模块

import random
#0~1的浮点随机数
ret=random.random()
#输出:0.11582781711340728 #1~3的整形数,包含3
ret=random.randint(1,3)
#输出:3
#1~3的整形数,不包含3
ret=random.randrange(1,3)
#输出:2 #列表中取值
ret=random.choice([11,22,33,44,55])
#输出:55 #选择多个,2代表2个
ret=random.sample([11,22,33,44,55],2)
#输出:[22, 33] #任意范围浮点数,如1~4
ret=random.uniform(1,4)
#输出:2.792166379341647 #打乱顺序
ret=[1,2,3,4,5]
random.shuffle(ret)
#输出:[5, 2, 1, 4, 3] print(ret) #产生随机4位验证码,数字字母都可能
def v_code():
ret=""
for i in range(4):
num=random.randint(0,9)
alf=chr(random.randint(65,122))
s=str(random.choice([num,alf]))
ret+=s
return ret
print(v_code())
#输出:94Ve

(三)os模块

#当前运行文件的工作目录
print(os.getcwd())
#输出:D:\03Study\day22\day22课件代码
#改变目录,相当于cd
os.chdir("..") #..向上一级目录,如工作目录下有名为“dir1”的目录可以写成os.chdir("dir1")
print(os.getcwd())
#输出:D:\03Study\day22 #返回当前目录
print(os.curdir)
#输出:.
#返回当前目录的父目录
print(os.pardir)
#输出:..
#可生成多层递归目录,如果有同名文件夹报错
os.makedirs('dirname1/dirname2')
#若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依次类推。如果目录有文件报错
os.removedirs("dirname1/dirname2")
#生成单级目录,相当于shell中的mkdir dirname
os.mkdir('dirname')
#删除单极空目录,若目录为不为空则无法删除,报错,相当于shell中的rmdir dirname
os.rmdir('dirname')
#列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
print(os.listdir())
#输出:['json&pickle.py', 'newname', 'os_test.py', 'output.xml', 're_lesson.py', 'sys_test.py', 'test.xml', 'xml_lesson', 'xml_test.py', '__init__.py', '序列化对象_pickle'] #删除一个文件
os.remove('dirname/we')
#重命名文件/目录
os.rename('dirname','newname')
#获取文件/目录信息
print(os.stat("newname/we"))
#输出:os.stat_result(st_mode=33206, st_ino=10977524091731226, st_dev=1692480672, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1549285018, st_mtime=1549285018, st_ctime=1549285018)
#操作系统特定的路径分隔符,win下为‘\\’,Linux下为‘/’
print(os.sep) #当前平台使用的行终止符,win下为‘\r\n’,Linux下为'\n'
print(os.linesep) #用于分割文件路径的字符串win下为;Linux下为:。比如在path系统环境变量里面分割项与项
print(os.pathsep) #输出字符串只是当前使用平台,win下为'nt',Linux为'posix'
print(os.name) #终端执行shell命令
print(os.system("dir"))
#获取系统环境变量
print(os.environ)
#输出:environ({'PATH': 'D:\\03Study\\venv\\Scripts;D:\\Python35\\Scripts\\;D:\\Python35\\;D:\\Python27\\;D:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Program Files (x86)\\Rational\\common;D:\\Program Files (x86)\\Rational\\Common', 'PROMPT': '(venv) $P$G', 'NUMBER_OF_PROCESSORS': '2', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'HOMEDRIVE': 'C:', 'USERPROFILE': 'C:\\Users\\fudonghai', 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 15 Stepping 13, GenuineIntel', 'ONEDRIVE': 'D:\\OneDrive', 'PYTHONUNBUFFERED': '1', 'LOCALAPPDATA': 'C:\\Users\\fudonghai\\AppData\\Local', 'APPDATA': 'C:\\Users\\fudonghai\\AppData\\Roaming', '_OLD_VIRTUAL_PATH': 'D:\\Python35\\Scripts\\;D:\\Python35\\;D:\\Python27\\;D:\\Python27\\Scripts;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Program Files (x86)\\Rational\\common;D:\\Program Files (x86)\\Rational\\Common', 'WINDOWS_TRACING_FLAGS': '3', 'PROCESSOR_LEVEL': '6', 'TMP': 'C:\\Users\\FUDONG~1\\AppData\\Local\\Temp', '_OLD_VIRTUAL_PROMPT': '$P$G', 'PYCHARM_MATPLOTLIB_PORT': '49323', 'SYSTEMDRIVE': 'C:', 'HOMEPATH': '\\Users\\fudonghai', 'COMPUTERNAME': 'FUDONGHAI-NOTE', 'FP_NO_HOST_CHECK': 'NO', 'PROCESSOR_REVISION': '0f0d', 'SESSIONNAME': 'Console', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'WINDIR': 'C:\\Windows', 'USERDOMAIN': 'fudonghai-Note', 'USERNAME': 'fudonghai', 'PYCHARM_HOSTED': '1', 'TEMP': 'C:\\Users\\FUDONG~1\\AppData\\Local\\Temp', 'PROGRAMDATA': 'C:\\ProgramData', 'PYTHONPATH': 'D:\\03Study;C:\\Program Files\\JetBrains\\PyCharm 2018.3.3\\helpers\\pycharm_matplotlib_backend', 'WINDOWS_TRACING_LOGFILE': 'C:\\BVTBin\\Tests\\installpackage\\csilogfile.log', 'VIRTUAL_ENV': 'D:\\03Study\\venv', 'PYTHONIOENCODING': 'UTF-8', 'PROGRAMFILES': 'C:\\Program Files', 'ALLUSERSPROFILE': 'C:\\ProgramData', 'SYSTEMROOT': 'C:\\Windows', '__COMPAT_LAYER': 'DisableUserCallbackException', 'TFS_DIR': 'D:\\Program Files (x86)\\ThinkVantage Fingerprint Software\\', 'LOGONSERVER': '\\\\FUDONGHAI-NOTE', 'OS': 'Windows_NT', 'PROGRAMW6432': 'C:\\Program Files', 'PSMODULEPATH': 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\;C:\\Program Files\\Intel\\', 'PUBLIC': 'C:\\Users\\Public', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files', 'PYCHARM': 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.3\\bin;'}) #把path分割成目录和文件名二元组返回
print(os.path.split(r"C:\Users\Administrator\脱产三期\day22\sss.py"))
#输出:('C:\\Users\\Administrator\\脱产三期\\day22', 'sss.py')
#返回path的目录,其实就是os.path.split的第一个元素
print(os.path.dirname(r"C:\Users\Administrator\脱产三期\day22\sss.py"))
#输出:C:\Users\Administrator\脱产三期\day22
#返回path最后的文件名,如path以/或者\结尾,那么就会返回空值。即os.path.split的第二个元素
print(os.path.basename(r"C:\Users\Administrator\脱产三期\day22\sss.py"))
#输出:sss.py #如果path存在,返回True;如果不存在,返回False
print(os.path.exists('D:\\03Study\day22\\day22课件代码\\newname'))
#输出:True #路径拼接
a="C:\\Users\\Administrator"
b="脱产三期\\day22\\sss.py"
print(os.path.join(a,b))
#输出:C:\Users\Administrator\脱产三期\day22\sss.py
#和文件时间相关的函数,原来上面讲过stat可以看到三个时间
print(os.stat("newname/we"))
#st_atime=1549375382, st_mtime=1549375382, st_ctime=1549285018 #返回path所指向的文件或者目录的最后存取时间
print(os.path.getatime("newname/we"))
#输出:1549375382.7303739
#返回path所指向的文件或者目录的最后修改时间
print(os.path.getmtime("newname/we"))
#输出:1549375382.731374
#返回path所指向的文件或者目录的建立时间
print(os.path.getctime("newname/we"))
#输出:1549285018.1002722

(四)sys模块

import sys
#命令行参数List,用于在程序初始化时接受参数,第一个元素是程序本身文件名
#在终端里面输入:python sys_test.py post D:/03Study/day22/day22课件代码/sys_test.py
print(sys.argv)
command=sys.argv[1]
path=sys.argv[2] if command=="post":
print('post') elif command=="get":
print('get')
'''输出:
['sys_test.py', 'post', 'D:/03Study/day22/day22课件代码/sys_test.py']
post
''' #获取Python解释程序的版本信息
print(sys.version) #获取最大的Int值
print(sys.maxsize)
#输出:9223372036854775807 #返回模块的搜素路径,初始化时使用PYTHONPATH环境变量的值
print(sys.path)
#输出:['D:\\03Study\\day22\\day22课件代码', 'D:\\03Study', 'D:\\03Study\\venv\\Scripts\\python35.zip', 'D:\\Python35\\DLLs', 'D:\\Python35\\lib', 'D:\\Python35', 'D:\\03Study\\venv', 'D:\\03Study\\venv\\lib\\site-packages', 'D:\\03Study\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.5.egg', 'D:\\03Study\\venv\\lib\\site-packages\\pip-10.0.1-py3.5.egg', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.3\\helpers\\pycharm_matplotlib_backend'] #获取操作系统平台名称
print(sys.platform)
#输出:win32 #进度条功能sys.stdout
import time
for i in range(100):
sys.stdout.write("#")
time.sleep(0.1)
sys.stdout.flush()
#输出进度条 #退出程序,正常退出时exit(0)
sys.exit(1)
#输出:Process finished with exit code 1

(五)json & pickle 模块

import json

#json.dumps会把所有的单引号变成双引号,再把数据变成json字符串
dic={'name':'alex'}#---->{"name":"alex"}----->'{"name":"alex"}'
i=8 #---->'8'
s='hello' #---->"hello"------>'"hello"'
l=[11,22] #---->"[11,22]" f=open("new_hello","w")
dic_str=json.dumps(dic)
f.write(dic_str) #上面两句等效一句:json.dump(dic,f),注意这个dump没有s
f.close() #json.loads把字符串还原成原数据格式
f_read=open("new_hello","r")
data=json.loads(f_read.read()) #上面两句等效一句:data=json.load(f),注意这个load没有s print(data)
print(type(data))
#输出:{'name': 'alex'}
#输出:<class 'dict'> #注意:loads前不是必须dump,只要符合json字符串的格式,可以直接loads
import json with open("Json_test","r") as f:
data=f.read()
data=json.loads(data)
print(data["name"])

pickle模块比json模块能处理更多的数据类型,但是对人来说可读性不好,所以使用范围并没有json广泛。

序列化:把对象从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,序列化之后,就可以把序列化之后的内容写入磁盘,或者通过网络传输到别的机器上。

反序列化:把变量的内容从序列化的对象重新读取到内存里称之为反序列化,即unpickling。

import pickle

dic = {'name': 'alvin', 'age': 23, 'sex': 'male'}

print(type(dic))  #<class 'dict'>

# --------序列化
j = pickle.dumps(dic)
print(type(j)) #<class 'bytes'> f = open('序列化对象_pickle', 'wb') #注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j) #等价于pickle.dump(dic,f)
f.close() # --------反序列化
f = open('序列化对象_pickle', 'rb')
data = pickle.loads(f.read()) # 等价于data=pickle.load(f)
print(data['age'])
#输出:23

(六)shelve模块

shelve模块把所有操作都变成字典。 会生成三个文件,后缀为bak,dat,dir

import shelve

f = shelve.open(r'shelve1')  # 目的:将一个字典放入文本 f={}

f['stu1_info']={'name':'alex','age':''}
f['stu2_info']={'name':'alvin','age':''}
f['school_info']={'website':'oldboyedu.com','city':'beijing'}
f.close() # print(f.get('stu1_info')['age'])
# print(f.get('school_info')['website'])
'''输出:
18
oldboyedu.com
'''

(七)xml模块

xml比json早,在很多领域已经使用,不容易替换。

import xml.etree.ElementTree as ET

#解析xml文件,得到文档树
tree = ET.parse("xml_lesson")
#得到根节点
root = tree.getroot()
#打印tag即为xml标签
print(root.tag)
#输出:data for i in root:
#标签名字
print(i.tag)
#属性
print(i.attrib)
for j in i:
#print(j.tag)
#print(j.attrib)
#内容
print(j.text)
'''输出:
data
country
{'add': 'yes', 'name': 'Liechtenstein'}
2
2010
141100
None
None
country
{'name': 'Singapore'}
5
2013
59900
None
country
{'name': 'Panama'}
69
2013
13600
None
None
''' # 遍历xml文档
for child in root:
print(child.tag, child.attrib)
for i in child:
print(i.tag, i.text) 只遍历标签为year的节点
for node in root.iter('year'):
print(node.tag, node.text)
'''输出:
year 2010
year 2013
year 2013
''' # 修改
for node in root.iter('year'):
new_year = int(node.text) + 1
node.text = str(new_year)
node.set("updated", "yes")
#写入文件才会生效
tree.write("xml_lesson") # 删除node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 4:
root.remove(country) tree.write('output.xml') #创建XML文件
new_xml = ET.Element("namelist") #创建根节点
#new_xml:处理对象,name:标签,attrib:属性
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
sex.text = ''
name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
age = ET.SubElement(name2, "age")
age.text = '' #生成文档对象
et = ET.ElementTree(new_xml)
et.write("test.xml", encoding="utf-8", xml_declaration=True) #ET.dump(new_xml) # 打印生成的格式
'''输出:test.xml
<?xml version='1.0' encoding='utf-8'?>
<namelist>
<name enrolled="yes">
<age checked="no" />
<sex>33</sex>
</name>
<name enrolled="no">
<age>19</age>
</name>
</namelist>
'''

(八)logging模块

1,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。

一般调试程序使用DEBUG输出大量日志信息,而生产环境使用WARNING往上减少无用信息

import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
'''输出:
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
'''

2,使用logging.basicConfig()进行初步配置,缺点是只能在屏幕或者文件择其一输出

logging.basicConfig(
level=logging.DEBUG, #设置输出级别
filename="loger.log", #输出到文件而不是到标准输出,默认采用追加模式
filemode="w", #把模式改为清空重写模式
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
# 时间 源文件名 [line:源文件行号] 级别 信息
datefmt='%a, %d %b %Y %H:%M:%S', #Wed, 13 Feb 2019 11:17:38
)
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')
'''输出:
Wed, 13 Feb 2019 11:17:38 s1.py[line:12] DEBUG debug message
Wed, 13 Feb 2019 11:17:38 s1.py[line:13] INFO info message
Wed, 13 Feb 2019 11:17:38 s1.py[line:14] WARNING warning message
Wed, 13 Feb 2019 11:17:38 s1.py[line:15] ERROR error message
Wed, 13 Feb 2019 11:17:38 s1.py[line:16] CRITICAL critical message
'''

可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有

filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
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用户输出的消息

3,logger对象:可以在屏幕和文件同时输出

例子一:

Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有"DEBUG"、"INFO"、"WARNING"、"ERROR"、"CRITICAL"。
最后使用Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出。

一般来说

def logger():
#创建logger对象
logger=logging.getLogger() #创建向文件里发送内容fh句柄
fh=logging.FileHandler("test_log")
#创建向屏幕里发送内容ch句柄
ch=logging.StreamHandler()
#添加句柄操作
logger.addHandler(fh)
logger.addHandler(ch) #日志格式设定
fm=logging.Formatter("%(asctime)s %(message)s")
#格式生效
fh.setFormatter(fm)
ch.setFormatter(fm) #日志级别
logger.setLevel("DEBUG") #返回对象
return logger #可以在任意一个py文件使用这个对象打印
ret=logger()
ret.debug("hello debug")
ret.info("hello info")
'''输出:文件和屏幕都会出现
2019-02-13 11:36:44,483 hello debug
2019-02-13 11:36:44,485 hello info
'''

logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。

例子二:两个logger对象

logger=logging.getLogger()

logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG) logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.WARNING) fh=logging.FileHandler("test_log-new")
ch=logging.StreamHandler() logger.addHandler(ch)
logger.addHandler(fh) logger1.addHandler(fh)
logger1.addHandler(ch) logger2.addHandler(fh)
logger2.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') logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message') logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
'''输出:logger1和logger2每个出现两次
logger warning message
logger error message
logger critical message
logger1 warning message
logger1 warning message
logger1 error message
logger1 error message
logger1 critical message
logger1 critical message
logger2 warning message
logger2 warning message
logger2 error message
logger2 error message
logger2 critical message
logger2 critical message
'''

这里有两个问题:

<1>我们明明通过logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为何显示的时候没有显示出DEBUG级别的日志信息,而是从WARNING级别的日志开始显示呢?

原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.WARNING)设置mylogger的日志级别为logging.WARNING,所以最后logger1的输出遵从了后来设置的日志级别。我的理解就是只存在两个对象默认的root根logger和儿子logger:logger1

  <2>为什么logger1、logger2对应的每个输出分别显示两次?

  这是因为我们通过logger = logging.getLogger()显示的创建了root Logger,而logger1 = logging.getLogger('mylogger')创建了root Logger的孩子(root.)mylogger,logger2同样。而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。

  ok,那么现在我们把

  # logger.addHandler(fh)

  # logger.addHandler(ch) 注释掉,我们再来看效果:

'''输出:logger1和logger2只出现一次
logger warning message
logger error message
logger critical message
logger1 warning message
logger1 error message
logger1 critical message
logger2 warning message
logger2 error message
logger2 critical message
'''

因为我们注释了logger对象显示的位置,所以才用了默认方式,即标准输出方式。因为它的父级没有设置文件显示方式,所以在这里只打印了一次。

孩子,孙子,重孙……可逐层继承来自祖先的日志级别、Handler、Filter设置,也可以通过Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。设置自己特别的日志级别、Handler、Filter。若不设置则使用继承来的值。

例子三:filter的使用限制只有满足过滤规则的日志才会输出。

比如我们定义了filter = logging.Filter('a.b.c'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带a.b.c前缀的Logger才能输出其日志。

import logging
def logger():
#创建logger对象
logger=logging.getLogger() #创建向文件里发送内容fh句柄
fh=logging.FileHandler("test_log")
#创建向屏幕里发送内容ch句柄
ch=logging.StreamHandler()
#添加句柄操作
logger.addHandler(fh)
logger.addHandler(ch) #日志格式设定
fm=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#格式生效
fh.setFormatter(fm)
ch.setFormatter(fm) # 定义一个filter
filter = logging.Filter('mylogger')
fh.addFilter(filter)
ch.addFilter(filter) #日志级别
logger.setLevel("DEBUG") #返回对象
return logger #可以在任意一个py文件使用这个对象打印
ret=logger()
ret.debug("hello debug")
ret.info("hello info")
'''输出:
如果filter设置为"root"则
2019-02-13 19:47:49,003 - root - DEBUG - hello debug
2019-02-13 19:47:49,004 - root - INFO - hello info
如果filter设置为"mylogger"则没有输出
'''

(九)configparser模块:写配置文件

1,创建一个配置文件

import configparser

#调用ConfigParser()实例化一个对象,就有了一个空字典
config = configparser.ConfigParser() #config={} #写法1,顶级键"DEFAULT"
config["DEFAULT"] = {'ServerAliveInterval': '',
'Compression': 'yes',
'CompressionLevel': ''} #写法2,顶级键'bitbucket.org'
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg' #写法3,顶级键'topsecret.server.com'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '' # mutates the parser
topsecret['ForwardX11'] = 'no' # same here #把对象写入文件
with open('example.ini', 'w') as f:
config.write(f)
'''输出:example.ini
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9 [bitbucket.org]
user = hg [topsecret.server.com]
host port = 50022
forwardx11 = no
'''

2,查example.ini

import configparser

#调用ConfigParser()实例化一个对象,就有了一个空字典
config = configparser.ConfigParser() #config={} config.read('example.ini') #sections()方法输出除了[DEFAULT]以外的顶级键
print(config.sections())
#输出:['bitbucket.org', 'topsecret.server.com'] #用来判断'bytebong.com'是否是顶级键
print('bytebong.com' in config)
# 输出:False #输出键的值
print(config['bitbucket.org']['User'])
#输出:hg
print(config['DEFAULT']['Compression'])
#输出:yes
print(config['topsecret.server.com']['ForwardX11']) #如果键名错误则程序报错
#输出:no #遍历顶级键下的键,把DEFAULT的也会输出
#所以DEFAULT里面一定放公共信息,这样其它键都能读取
for key in config['topsecret.server.com']:
print(key)
'''输出:
host port
forwardx11
serveraliveinterval
compression
compressionlevel
''' #options功能是取键
print(config.options('bitbucket.org'))
#输出:['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11'] #items取键和值
print(config.items('bitbucket.org'))
#输出:[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')] #get可以连续放入键及其子键
print(config.get('bitbucket.org','compression'))
#输出:yes

3,增删改

import configparser

#调用ConfigParser()实例化一个对象,就有了一个空字典
config = configparser.ConfigParser() #config={} config.read('example.ini')
#增加顶级键yuan
config.add_section('yuan')
#增加顶级键下面的键值对
config.set('yuan','k1','') #删除顶级键,连同下面的内容全部删除
config.remove_section('yuan')
#删除顶级键下面的键值对
config.remove_option('bitbucket.org','user') #写入才能生效
with open('example.ini', 'w+') as f:
config.write(f) #另一种写法,不需要close
#config.write(open('i.cfg', "w"))

(十)hashlib模块:hash算法,摘要算法

用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib

m=hashlib.md5()# m=hashlib.sha256()

m.update('hello'.encode('utf8'))
print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 m.update('alvin'.encode('utf8')) print(m.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af m2=hashlib.md5()
m2.update('helloalvin'.encode('utf8'))
print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af

上面,先update("hello"),然后update("alvin")的结果和直接update("helloalvin")一样

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

import hashlib

obj = hashlib.md5("private".encode('utf-8'))#括号里面的称为“盐”
obj.update("hello".encode("utf-8")) print(obj.hexdigest()) #没有加盐:5d41402abc4b2a76b9719d911017c592
#加盐后 :fc820a1cfa3dc4e81efb96c61fe9b981

SHA256算法和MD5算法的用法是一样的,坚固程度好一点

import hashlib

# ######## 256 ########

hash = hashlib.sha256('898oaFs09f'.encode('utf8'))
hash.update('alvin'.encode('utf8'))
print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7

参考:http://www.cnblogs.com/yuanchenqi/articles/5732581.html

【笔记】Python基础六:模块module介绍及常用模块的更多相关文章

  1. 第六篇:python基础_6 内置函数与常用模块(一)

    本篇内容 内置函数 匿名函数 re模块 time模块 random模块 os模块 sys模块 json与pickle模块 shelve模块 一. 内置函数 1.定义 内置函数又被称为工厂函数. 2.常 ...

  2. Nodejs学习笔记(十六)--- Pomelo介绍&入门

    目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...

  3. Nodejs学习笔记(十六)—Pomelo介绍&入门

    前言&介绍 Pomelo:一个快速.可扩展.Node.js分布式游戏服务器框架 从三四年前接触Node.js开始就接触到了Pomelo,从Pomelo最初的版本到现在,总的来说网易出品还算不错 ...

  4. 孤荷凌寒自学python第六十八天学习并实践beautifulsoup模块1

    孤荷凌寒自学python第六十八天学习并实践beautifulsoup模块1 (完整学习过程屏幕记录视频地址在文末) 感觉用requests获取到网页的html源代码后,更重要的工作其实是分析得到的内 ...

  5. python爬虫:爬虫的简单介绍及requests模块的简单使用

    python爬虫:爬虫的简单介绍及requests模块的简单使用 一点点的建议: (学习爬虫前建议先去了解一下前端的知识,不要求很熟悉,差不多入门即可学习爬虫,如果有不了解的,我也会补充个一些小知识. ...

  6. 进击的Python【第五章】:Python的高级应用(二)常用模块

    Python的高级应用(二)常用模块学习 本章学习要点: Python模块的定义 time &datetime模块 random模块 os模块 sys模块 shutil模块 ConfigPar ...

  7. python基础知识1---python相关介绍

    阅读目录 一 编程与编程语言 二 编程语言分类 三 主流编程语言介绍 四 python介绍 五 安装python解释器 六 第一个python程序 七 变量 八 用户与程序交互 九 基本数据类型 十 ...

  8. Python图形图像处理库的介绍之Image模块

    http://onlypython.group.iteye.com/group/wiki/1372-python-graphics-image-processing-library-introduce ...

  9. python基础六

    模块 1.定义: 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test) 包:用来从逻辑上 ...

随机推荐

  1. 利用grep参数查看某关键词前后几行内容

    查看文件中含有“哈哈哈”关键字所在行后5行内容 cat xxxxxx | grep -A 5 哈哈哈 查看文件中含有“哈哈哈”关键字所在行前5行内容 cat xxxxxx | grep -B 5 哈哈 ...

  2. docker 快速部署ES集群 spark集群

    1) 拉下来 ES集群  spark集群 两套快速部署环境, 并只用docker跑起来,并保存到私库. 2)弄清楚怎么样打包 linux镜像(或者说制作). 3)试着改一下,让它们跑在集群里面. 4) ...

  3. JavaScript最后的课程笔记

    一.快捷位置和尺寸 DOM已经提供给我们计算后的样式,但是还觉得不方便,所以DOM又提供给我们一些API: ele.offsetLeft ele.offsetTop ele.offsetWidth e ...

  4. C++Primer第五版——习题答案目录

    目前正在刷<C++Primer>这本书,会在博客上记录课后习题答案,答案仅供参考. 因为水平有限,如有有误之处,希望大家不吝指教,谢谢! 目录地址 使用的系统为:win 10,编译器:VS ...

  5. 使用nginx实现一个主机部署多域名指向不同docker项目

     1,安装 docker yum install docker 使用Docker 中国加速器 vim /etc/docker/daemon.json 添加下面代码 { "registry-m ...

  6. Scrapy CrawlSpider源码分析

    crawl.py中主要包含两个类: 1. CrawlSpider 2. Rule link_extractor:传LinkExtractor实例对象 callback:传”func_name“ cb_ ...

  7. css选择器区别

    空格选择器 ul li 选择ul 下面的所有li 元素 大于号选择器  ul>li 选择ul 下面的直接子元素 只能是儿子辈的 不能是孙子辈的

  8. VMware12 安装 Mac OS 10.12 步骤及设置优化教程

    最近公司要开发苹果的ARKit应用,但是项目组穷啊,只有美工用着一台苹果本本,所以肯定不能老用他的电脑,效率低还老打扰他.所以我就想着用虚拟机整,毕竟玩了N年的虚拟机了,应该是没啥问题的.所以就开始各 ...

  9. Python-10 字典dict

    #1 创建 dict1={'欢欢':'i love','小高高':'you'} dict2={1:'one',2:'two',3:'three'} dict3={} #2 访问元素 print('欢欢 ...

  10. 【Nginx】实现负载均衡

    负载均衡是什么? 当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃.为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力. 我 ...