模块(module)的概念:
为了维护代码(最大的好处),把很多函数分组,分别放到不同的文件里;在Python中,一个.py文件就是就称之为一个模块
其次,编写代码不必从零开始,当一个模块编写完毕,就可以在其他地方被引用。模块一共分3种:1)python标准库;2)第三方模块;3)应用程序自定义模块。(自己写模块时不要和已有的模块 重名,或者新建文件夹建重名的)
#文件夹和python packa的区别:包里面会多一个_init_.py的空文件,包的功能是组织模块:存放某一功能的各种模块,方便存放与取用。
引用模块时,要注意路径,如果与执行文件在同一级文件时可以直接引用,如果在执行文件的下一层,可以相对引用。(只能识别与执行文件所在的同一层级,其他的引用都要加相对或者绝对引用)
引入其他自写模块时,都以当前执行文件的模块为路径进行查找,而不会以引入模块的路径去查找
# import cal #引入模块时:1.执行对应py文件(全部执行);2.引入变量名 (cal模块是自己编写的) # print(cal.add(3,5)) # # # from functools import * #引入包里的全部变量,不推荐此方法,里面的函数名称太多,可能和自己写的函数名相同 # from functools import reduce # print(reduce(lambda x,y:x*y,[3,4,5])) # from my_module import cal_new #相对引用,cal_new.py是下层文件
# print(cal_new.add(3,5))
# from my_module.web1.cal import add #从当前路径开始引用更深层次路径的py文件
# print(add(3,4))
# from my_module.web1 import cal #也可以调用,和上面功能相同
# print(cal.add(3,4))
# from my_module import web1 #不可以,这个执行的是_init_.py文件
# print(web1.cal.add(3,4))
__name__的两个意义:
在执行文件打印的时候就是字符串__main__;在调用文件里打印时就是打印调用文件的地址
print('ok0') def add(x,y): print('ok1') return x+y def sub(x,y): print('ok2') return x-y print(__name__) if __name__ == '__main__': #做调用文件时:用于被调用函数的测试;做执行文件时:在别人调用函数时不启动主程序,自己执行时才启动 print(add(3,4))
time模块:
import time # #时间戳 # print(time.time()) #从1970年1月1日到现在一共经历了多少秒 # #结构化时间 # print(time.localtime()) #本地的结构化时间 # # t=time.localtime() # print(t.tm_year) # print(t.tm_wday) # # print(time.gmtime()) #世界标准时间的结构化时间(格林威尔时间,与东八区差8小时) # #结构化时间——时间戳,由时间戳转化为结构化时间就是localtime和gmtime,默认参数就是当前时间戳;结构化时间转化为时间戳,用mktime # print(time.localtime(1609730674.0720983)) # print(time.mktime(time.localtime())) # #结构化时间——字符串时间,由结构化时间转换成字符串时间用strftime,将字符串转换为结构化时间用strptime # print(time.strftime('%Y-%m-%d %X',time.localtime())) #X表示时分秒 # print(time.strptime('2021:01:04:12:04:56','%Y:%m:%d:%X')) # print(time.asctime()) #将结构化时间转换成固定格式的字符串时间,不用写格式,更便利 # print(time.ctime()) #将时间戳转换成固定格式的字符串时间,不用写格式,更便利 #time.sleep()线程推迟指定的时间运行,单位为秒。 # import datetime #另一个模块下的显示时间 # print(datetime.datetime.now())
random模块:
import random # print(random.random()) #随机取(0,1)的float # print(random.uniform(0,2))#随机取范围内的float # print(random.randint(1,3)) #随机取[1,3]的整数 # print(random.randrange(1,3)) #随机取[1,3)的整数 # print(random.choice([11,22,33,44])) #随机选取一个列表里的元素,可以依据元素个数定比例 # print(random.sample([11,22,33,44],2)) #随机选取列表里的规定个数的元素,组成新列表 # ret = [1,3,5,7,9] # random.shuffle(ret) #打乱列表的顺序 # print(ret) #练习:制作5位随机验证码 def v_code(): ret='' for i in range(5): num=random.randint(0,9) alp=chr(random.randint(65,122)) #chr在ASCII中根据数字取字母 s=str(random.choice([num,alp])) ret += s return ret print(v_code())
os模块:
import os # print(os.getcwd()) #获取当前工作文件的目录路径 # os.chdir("..") #改变工作脚本的目录,相当于shell下的cd # print(os.getcwd()) # os.chdir('python练习') # print(os.getcwd()) # os.curdir #代表返回当前目录,也可用os.chdir(".") # print(os.getcwd()) # os.pardir #,代表获取当前目录的父目录字符串名,也可用os.chdir("..") # print(os.getcwd()) # os.makedirs('text1/text2') #在当前目录建立递归文件目录 # os.removedirs('text1/text2') #删除目录文件,如果目录文件不为空,则不能删,要指定全部删才能删掉 # os.remove() #也是删除文件,与上面一样 # print(os.listdir()) #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 # print(os.stat('人口普查')) #获取文件或目录信息 # print(os.sep) #输出操作系统特定的路径分隔符(win:"\" linux:"/")在不清楚操作系统下使用 # print(os.linesep) #输出操作系统特定的行终止符(win:"\r\n" linux:"\n")在不清楚操作系统下使用 # print(os.pathsep) #输出操作系统用于分割文件路径的字符串(win:";" linux:":") # print(os.name) #输出字符串指示当前使用平台(win:"nt" linux:"posix") # print(os.system('time模块.py')) #运行shell命令,直接显示指定文件 # print(os.environ) #获取系统环境变量 # print(os.path.split(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #将path分割成目录和文件名,以元组返回 # print(os.path.dirname(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #返回path目录,即上顺元组的第一个值 # print(os.path.basename(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #返回path文件名,即上顺元组的第二个值(如果path以/或\结尾,返回空) # print(os.path.exists(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #path是否存在(path以/或\结尾即不存在) # print(os.path.isabs(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #如果是绝对路径,返回True # print(os.path.isfile(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #如果是一个存在的文件,返回True # print(os.path.isdir(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #如果是一个存在的目录 ,返回True # #重点: # a = "C:Users\Lenovo\Desktop" # b = "python练习\sys模块.py" # print(os.path.join(a,b)) #将多个路径组合后返回,第一个绝对路径之前的参数将被省略 # print(os.path.getatime(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #获取变量最后一次的访问时间 # print(os.path.getmtime(r'C:\Users\Lenovo\Desktop\python练习\sys模块.py')) #获取变量最后一次的修改时间
sys模块:
import sys # sys.path.append() #增加(修改)环境变量,这是暂时性的,永久的修改在计算机属性里 # import os # print(os.path.dirname(os.path.abspath(__file__))) #返回上一级路径,os.path.abspath(__file__)是当前位置文件的绝对地址 # print(os.path.abspath(__file__)) # print(sys.path) #返回模块的搜索路径,初始化时使用pythonpath环境变量的值 # sys.exit() #退出程序,exit(0)为正常退出 # print(sys.version) #获取python解释程序到的版本信息 # print(sys.platform) #返回操作系统平台名称 # #重点 # print(sys.argv) #在命令提示符执行,输出命令行参数list,第一个元素是程序本身路径,(有此参数后,命令提示符输入的其他值也可以保留下来,作为执行程序的启动指令) # x = sys.argv[2] # if sys.argv[1]=='sb': # print('sbbb') # sys.stdout.write('#') #打印内容,再次重复代码会在原来打印的内容上叠加 # sys.stdout.write('#') # import time #制作进度条 # for i in range(10): # sys.stdout.write('#') # time.sleep(1)
json&pickle模块(数据交换):
import json # dic = {'name':'lyt'} # data = json.dumps(dic) #将其他类型的数据转换为字符串类型的数据,且原数据里面的单引号均变为双引号(能够适用于各种编程语言) # print(data) # print(type(data)) # # s = json.loads(data) # print(s) # print(type(s)) #将字符串类型的数据还原为json.dumps之前原来类型的数据(符合json字符串的没经过dumps也可以loads)(json封装后可作为一个桥梁,可以使数据在各种语言之间相互转换) # f = open('json测试','w') # # k=json.dumps(s) # # f.write(k) # json.dump(s,f) #相当于前两步,省略了写,不推荐 # g = open('json测试','r') # e = json.load(g) #省略了读数据这一步,不推荐 # print(type(e)) import pickle dic = {'name':'lyt'} data = pickle.dumps(dic) #将其他类型的数据转换为字节形式(pickle和json的dumps都称为序列化,pickle序列的类型更多) print(type(data)) # f = open('pickle测试','wb') # f.write(data) #w写入str,wb写入的是bytes import pickle k = open('pickle测试','rb') t = pickle.loads(k.read()) print(t)
shelve模块:
#和json作用差不多,使用简单但使用的范围小 import shelve f = shelve.open(r'shelve') #目的:将一个字典放入文本 f['stu1_info']={'name':'alex','age':18} f['stu1_info']={'name':'ppp','age':20} f['school_info']={'websits':'zncj','city':'wh'} f.close() f = shelve.open(r'shelve') print(f.get('stu1_info')) print(f.get('stu1_info')['age'])
xml模块:
#作用和json相似,出现得更早,目前广泛应用 import xml.etree.ElementTree as ET tree = ET.parse('xml_lesson1') #读取 root = tree.getroot() #拿到根节点(xml是一个树枝结构) print(root.tag) #tag拿到的是标签名(在xml文件中为黄色),不是属性及值 for i in root: print(i.tag) for j in i: print(j.tag) print(j.attrib) #attrib拿的是属性,以字典显示(在xml文件中有等号) print(j.text) #text拿的是标签的值,(在xml文件中有夹在标签名之中) for node in root.iter('year'): #只遍历year节点 print(node.tag,node.text) new_year = int(node.text) + 1 #修改 node.text = str(new_year) node.set("updated","yes") #增加属性 tree.write("xml_test.xml") #这一步表示将内存里修改好的保存在硬盘 for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write("output.xml") #删除 #创建标签 new_xml = ET.Element("namelist") name1 = ET.SubElement(new_xml,"name1",attrib={'enrolled':'yes'}) age = ET.SubElement(name1,"age",attrib={'cheched':'no'}) sex = ET.SubElement(name1,'sex') sex.text = '33' name2 = ET.SubElement(new_xml,"name2",attrib={'enrolled':'no'}) age = ET.SubElement(name2,"age",attrib={'cheched':'no'}) sex = ET.SubElement(name2,'sex') age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象 et.write("new_list.xml",encoding="utf_8",xml_declaration=True)
re模块(正则表达式):
正则表达式是一种小型的、高度专业的编程语言,所有编程语言都可以用,内嵌在python中,通过re模块实现,用于处理字符串(比如模糊匹配)
1.普通字符:大多数字符和字母都会和自身匹配(精准匹配)
2.元字符:. ^ $ * + ? {} [] | () \
s = 'djfgndkwiodwndfnwdasklnnjlytncvsdnc' print(s.find('lyt')) # .为通配符,除了\n换行不行 import re print(re.findall("l.t",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc')) # ^指只能在字符串开头匹配才能成功 print(re.findall("^l.t",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc')) print(re.findall("^d.f",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc')) #前三个字符必须是规定的 # $指只能在字符串结尾匹配才能成功 print(re.findall("s..c$",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc')) #后4个字符必须是规定的 print(re.findall("s..c$",'djfgndkwiodwndfnwdasklnnjlxtncvsdnc$')) #不能匹配上,$在字符串中是普通字符,而非元字符 # *表示重复,重复紧挨着的字符串,可以重复0到无穷次;+也表示重复,可以重复1到无穷;?重复0或者一个(均为贪婪匹配,有多少匹配多少) print(re.findall("s*",'djfgndkwiodwnssssdfnwdasklnnjlxtncvsdnc$')) print(re.findall("alex*",'qweruhrnalexxxxjndn')) print(re.findall("alex+",'qweruhrnalexxxxjndn')) print(re.findall("alex*",'qweruhrnalejndn')) # x*的x起修饰作用,自身并不算一个 print(re.findall("alex+",'qweruhrnalejndn')) #+号不能匹配0个 print(re.findall("alex?",'qweruhrnalejndn')) print(re.findall("alex?",'qweruhrnalexxjndn')) #{0,}相当于*;{1,}相当于+;{0,1}相当于?;{6}表示固定几个;{a,b}表示范围。 print(re.findall("alex{6}",'qweruhrnalexxxxxxxjndn')) print(re.findall("alex{6}",'qweruhrnalexxjndn')) # 在贪婪匹配后加?表示惰性匹配,按最少的去匹配 print(re.findall("alex*?",'qweruhrnalexxxxjndn')) print(re.findall("alex+?",'qweruhrnalexxxxjndn')) #字符集[]表示或 print(re.findall("x[yz]",'xydfjjsxz')) #findall返回所有满足匹配条件的结果,放在列表里 print(re.findall("x[yz]p",'xydfjjsxzp')) print(re.findall("x[y,z]",'x,ydfjjsxzp')) #在[]里逗号(,)或者星(*)等元字符算普通字符,除-(表示范围);^(表示非);\()是特殊意义 print(re.findall("x[y*z]",'x,ydfjjsx*zp')) print(re.findall("x[a-z]",'x,ydfjjsxbp')) print(re.findall("x[a-z]*",'x,ydfjjsxbp')) #这里的*表示a到z的都可以重复 print(re.findall("x[^a-z]",'x,ydfjjsxbpx12')) #除a-z中其他的都可匹配 # \后边跟元字符去除特殊功能;\后边跟普通字符实现特殊功能 print(re.findall("\d",'2345x,ydfjjsxbpx12')) #d选出字符串中的数字,D取出非数字(大小写功能相反) print(re.findall("\d+",'2345x,ydfjjsxbpx12')) print(re.findall("\s",'2345x, ydfjjsxbpx12')) #s取出空白,S取出所有非空白 print(re.findall("\S+",'2345x, ydfjjsxbpx12')) print(re.findall("\w",'2345x, ydfjjsxbpx12')) #w匹配所有字母数字字符,W相反 print(re.findall("\b",'2345x, y&dfjjs#xbpx12')) #\b匹配一个特殊字符边界,比如空格,&,#等 print(re.findall("www\.baidu","www:baidu")) #去掉特殊功能 print(re.findall("www.baidu","www:baidu"))
import re
print(re.findall('I',"Hello I am LISA"))
print(re.findall('^I',"Hello I am LISA"))
print(re.findall('^I',"I am LISA"))
print(re.findall('I\b',"Hello I am LISA")) #不能匹配出来,要用下两种方法
print(re.findall(r'I\b',"Hello I am LISA")) #\b表示匹配特殊字符,加上r表示python不进行任何转译,将内容直接传给re执行
print(re.findall('I\\b',"Hello I am LISA")) #\\表示python转译时去掉\的特殊意义,将内容传给re后有一个\,对应\b(多个\也遵循此逻辑)
print(re.findall('ka|b','sddjkasf'))
print(re.findall('ka|b','sddjkbsf'))
print(re.findall('ka|b','sddjkabsf')) #|表示或
print(re.findall('(a.c)','abcabcabc')) #()表示分组,把括号里的当作一个整体
print(re.search('(a.c)','adcabcabc')) #search表示匹配到第一个结果就返回,结果存在一个对象中,通过group取用;匹配失败返回空
print(re.search("(?P<name>[a-z]+)","alex20lyt18").group())
ret=re.search("(?P<name>[a-z]+)(?P<age>\d+)","alex20lyt18") #加入此格式表示分组并对组进行命名,<>为命名,方便查询不同组的数据(P为大写)
print(ret.group('name'))
print(re.match('\d+',"alex34lyt20")) #match跟search功能相同,但必须在开头匹配成功,相当于search('^\d+',"alex34lyt20")
print(re.split("[ |]","hello we|sdf")) #split 以指定符号为分隔符,切分文本(分隔符会被去掉)
print(re.split('[ab]','abc')) #split会将得到的结果再次分割,直到不能再分割了为止
print(re.sub('\d+','A','sdjf654fhgjd67')) #sub表示替换,一般需要三个参数
print(re.sub('\d+','A','sdjf654fhgjd67',1)) #第四个参数表示要替换的次数
print(re.subn('\d+','A','sdjf654fhgjd67')) #比sub功能多一个替换的次数
com=re.compile('\d+') #compile表示先编译模糊匹配的功能,后面直接用就行(可多次执行,效率比findall('\d+','ashdfh34ghehf56')高一点)
print(com.findall('ashdfh34ghehf56'))
print(re.finditer('\d+','ashdfh34ghehf56')) #区别在于findall的是,得到的是迭代器对象
print(re.findall("www\.(baidu|163)\.com","www.baidu.com")) #即使匹配成功,优先给出组里(即括号)的内容
print(re.findall("www\.(?:baidu|163)\.com","www.baidu.com")) #取消组的优先级
s = "12+(56-7*(7*8-2)+20)"
print(re.search("\([^()]+\)",s).group()) #查找最里层的括号里的内容
logging模块:
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 字符串形式的当前时间
%(thread)d 线程ID,可能没有
%(threadName)s 线程名,可能没有
%(process)d 进程ID,可能没有
%(message)s 用户输出的消息
import logging # # logging.basicConfig( # level=logging.DEBUG, #设置rootlogger的日志级别,可更换默认层级 # filename='logger.log', #用指定的文件名创建FieldHandler,这样日志会被储存在指定的文件中(filename会将日志输出到文件,stream则将输出到屏幕) # filemode="w", #设置写入(打开)方式,默认为a追加 # format="%(asctime)s %(lineno)s %(message)s %(filename)s" #指定日志的显示格式,往%()加入想要的格式就行 # #datefmt指定日期时间格式 # #stream指定的stream创建streamhandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为前者。若同时列出了filename和stream两个参数,则stream参数会被忽略 # ) # # logging.debug('debug message') # logging.info('info message') # logging.warning('Hello') # logging.error('error message') # logging.critical('critical message') #表示在对应层级加入日志,级别越来越重要,默认的level是warning级别,只显示其以后的级别(包括自己) # #logger对象 # def test(): # logger=logging.getLogger() #创建可吸收其他日志的对象 # fh=logging.FileHandler("test_log") #创建文件日志 # ch=logging.StreamHandler() #创建屏幕日志 # fm=logging.Formatter("%(asctime)s %(message)s")#设置日志的格式 # fh.setFormatter(fm) #将格式给予日志 # ch.setFormatter(fm) # logger.addHandler(fh) #吸收日志 # logger.addHandler(ch) # logger.setLevel("DEBUG") # return logger # #可将上述设置成一个函数以便需要时调用 # logger=test() # logger.debug('debug message') # logger.info('info message') # logger.warning('Hello') # logger.error('error message') # logger.critical('critical message') # logger1=logging.getLogger('mylogger') #默认是root用户建立的对象,这里是子目录mylogger创建的,一个目录只能有一个级别,所以只能打印8条记录 # logger1.setLevel(logging.DEBUG) # # logger2=logging.getLogger('mylogger') # logger2.setLevel(logging.INFO) # # fh=logging.FileHandler("test_log_NEW") # ch=logging.StreamHandler() # fm=logging.Formatter("%(asctime)s %(message)s") # fh.setFormatter(fm) # ch.setFormatter(fm) # # logger1.addHandler(fh) # logger1.addHandler(ch) # # logger2.addHandler(fh) # logger2.addHandler(ch) # # logger1.debug('debug message') # logger1.info('info message') # logger1.warning('Hello') # logger1.error('error message') # logger1.critical('critical message') # # logger2.debug('debug message') # logger2.info('info message') # logger2.warning('Hello') # logger2.error('error message') # logger2.critical('critical message') logger=logging.getLogger() logger.setLevel(logging.DEBUG) logger1=logging.getLogger('mylogger') #树形关系,mylogger是root的子目录,它打印时有几个父辈级就将自身的内容再多打印几份 logger1.setLevel(logging.INFO) fh=logging.FileHandler("test_log_NEW1") ch=logging.StreamHandler() fm=logging.Formatter("%(asctime)s %(message)s") fh.setFormatter(fm) ch.setFormatter(fm) logger.addHandler(fh) logger.addHandler(ch) logger1.addHandler(fh) logger1.addHandler(ch) logger.debug('debug message') logger.info('info message') logger.warning('Hello World') logger.error('error message') logger.critical('critical message') logger1.debug('debug message') logger1.info('info message') logger1.warning('Hello') logger1.error('error message') logger1.critical('critical message')
configparser(配置文件解析)模块:
配置文件:类字典文件,包含块和值(键值对)
import configparser # config = configparser.ConfigParser() #相当于建了一个空字典{} # # config["DEFAULT"] = {'ServerAliveInterval':'45', # 'Compression':'yes', # 'CompressionLevel':'9', # 'ForwardXll':'yes'} #给DEFAULT关键字对应值 # # with open('example.ini','w')as f: # config.write(f) #把配置文件写入文件里 #配置文件的增删改查 config = configparser.ConfigParser() config.read('example.ini') #读 print(config.sections()) #拿到除default外的块(即关键字) print('bitbucket.org' in config) #判断块在不在配置文件里 print(config['bitbucket.org']['user']) #在块下面取值,不区分大小写 for key in config['bitbucket.org']: #遍历块的值的时候,都会遍历出默认块的值(块的值也是一个字典) print(key) print(config.options('bitbucket.org')) #与for循环的遍历功能相似,取出值对应的字典的键,输出为一个列表 print(config.items('bitbucket.org')) #取出块的值,输出为一个列表 print(config.get('bitbucket.org','user')) #取出块的值对应的字典的值 config.add_section('yuan') #增加块 config.set('yuan','k1','1111') #添加块下的值 config.write(open('i.cfg','w')) config.remove_section('yuan') #删除块 config.remove_option('bitbucket.org','port') #删除块对应的某些值 config.write(open('i-1.cfg','w'))
配置文件范例:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardXll = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardXll = no
hashlib模块:
用于加密相关操作,python3里代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法。(摘要算法,将明文转换为密文,单向操作)
位数是固定的,均为32位
import hashlib obj = hashlib.md5() obj.update('hello'.encode("utf8")) print(obj.hexdigest()) #普通的加密,得到原生的hash值,容易通过数据库中hash值与明文的对应进行反解 #加盐,生成的密文变成独一无二的hash值 obj = hashlib.md5('lyt'.encode("utf8")) obj.update('hello'.encode("utf8")) #如果第一段代码执行,再执行这一段代码,相当于执行update('hellohello'),即叠加 print(obj.hexdigest()) #其他算法与此类似,更换算法名即可
浙公网安备 33010602011771号