python第五周:模块、标准库
模块相关知识:
定义:用来从逻辑上组织python代码(变量、函数、类、逻辑:实现一个功能)本质就是以.py结尾的python文件(文件名:test.py,对应的模块名:test)
附注:包:是用来从逻辑上组织模块的,本质就是一个目录(必须带有一个_init_.py文件)
导入方法:
(1)import module_name import module1_name,module2_name
(2)from module_1 import * from module_1 import m1,m2,m3 from modul_1 import logger as logger_1
import本质(路径搜索和搜索路径):
导入模块的本质就是把python文件解释一遍。要解释该python文件,就要先找到这个模块在哪儿(即这个模块的路径位置)
举例:
(1)import module_1,本质就是把module_1中的所有代码解释了一遍复制给module_1 = (all_code)
调用方式:module_1.name,module_1.say_hello()
(2)from module_1 import name,本质就是把modul_1中的name变量放到当前位置并执行name = "Mr Wu"
导入包的本质就是解释该包下的_init_.py文件
模块的分类:
a:标准库
b:开源模块
c:自定义模块
标准库:
(1)time和datetime
再python中,通常由这几种方式来表示时间:1)时间戳 2)格式化的时间字符串 3)元组(struc_time)共九个元素。由于python中的时间模块实现主要调用c库,所以各个平台上可能有所不同。
附注:UTC即格林威治天文时间,世界标准时间。再中国为UTC+8,DST即夏令时。
时间戳:通常来说,时间戳表示的是从1970年1月一日00:00:00开始按秒计算的偏移量。我们运行:"type(time.time())",返回的是float类型。返回时间戳方式的函数主要有time(),clock()
元组方式:struct_time元组共有九个元素,返回struct_time的函数主要有gmtime(),localtime(),strftime()。
import time t = time.time()#获取时间戳
time.localtime(t)#获取UTC+*的struct_time元组
time.gmtime(t)#获取UTC的struct_time元组 strftime("格式",struct_time)---->"格式化字符串" strptime("格式化的字符串","格式")---->struct_time >>>time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) #%Y:x.tm_year %m:x.tm_mon "2018-09-25 20:19:34" >>>time.strptime("2018-09-25 20:19:34","%Y-%m-%d %H:%M:%S") time.struct_time(tm_year=2018,tm_mon=9,tm_mday=25,tm_hour=20,tm_min=19,tm_yday=233,tm_isdst=-1) import datetime datetime.datetime.now() #获取当前时间:datetime.datetime(2018, 9, 25, 20, 59, 49, 449321) datetime.datetime.now()+datetime.timedelta(m) #m天后的时间:2018-09-25+m 21:03:41.081737 datetime.datetime.now()+datetime.timedelta(hours=m) #m个小时后的时间:2018-09-25 21+m:03:41.081737 datetime.datetime.now()+datetime.timedelta(minutes=m) #m分钟后的时间:2018-09-25 21:03+m:41.081737 c_time = datetime.datetime.now() print(c_time.replace(minute=3,hour=2)) #时间替换,2018-09-25 02:03:41.081737
(2)random模块:
print(random.random()) #0.829382 #random.random()用于生成一个0到1之间的随机浮点数 print(random.uniform(1,10)) #random.uniform(n,m)用于生成一个n到m之间的随即浮点数 print(random.randint(1,7)) #4 #random.randint()的函数原型是:random.randint(a,b),用于生成一个指定范围内的整数。 #其中参数a是上限,参数b是下限,生成的随机数:a<=n<=b print(random.randrange(1,10) #5 #random.randrange()的函数原型为:random.randrange([start],stop[,step]), #从指定范围内,按指定基数递增的集合中 获取一个随机数。如:random.randrange(10,100,2), #结果相当于从[10,12,14......,96,98]序列中获取一个随机数 #random.randrange(10,100,2)在结果上与random.choice(range(10,100,2))等效 print(random.choice("liukuni")) #1 #random.choice从序列中获取一个随机元素。 #其函数原型为:random.choice(sequence)。参数sequence表示一个有序类型。 #这里说明一下:sequence在python中不是一种特定的类型,而是泛指一系列的类型 #list、tuple、字符串都属于sequence #下面是使用了choice的一些例子: print(random.choice("学习python")) #学 print(random.choice(["JGood","List","Dict"]) ) #List print(random.choice(("Tuple","List","Dict")) #List print(random.sample([1,2,3,4,5],3)) #[1,2,5] #random.sample的函数原型为:random.sample(sequence,k),从指定序列中随机获取指定长度的片段 #sample不会修改函数原型 print(random.uniform(1,10)) #random.uniform(n,m)用于生成一个n到m之间的随即浮点数 #洗牌 items = [1,2,3,4,5,6,7] print(items) #[1,2,3,4,5,6,7] random.shuffle(items) print(items) #[1,4,7,2,5,3,6]
(3)os模块
提供对操作系统进行调用的接口:
os.getcwd()获取当前工作目录,及当前脚本工作的目录路径 os.chdir("dirname")改变当前脚本工作目录,相当于shell下cd os.curdir 返回当前目录:('.')(代表当前目录) os.pardir 获取当前目录的父目录的字符串名:('..')(代表父集目录) os.makedirs("dirname1/dirname2") 可生成多层递归目录 os.removedirs("dirname1") 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.mkdir("dirname") 生成单级目录,相当于shell中的mkdir dirnmae os.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 输出用于分割文件路径的字符串 os.name 输出字符串指示当前使用平台,win->"nt",Linux->"posix" os.system("bash command") 运行shell命令,直接显示 os.environ 获取系统环境变量 os.path.abspath(path) 返回path规范化的绝对路径 os.path.spilt(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,否则返回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所指向的文件或者目录的最后修改时间
(4)sys模块
#sys.argv,获取命令行参数list,第一个元素是程序本身的路径 print(sys.argv)#['F:/python学习/projects/s14/day5/练习1.py'] #sys.exit(n),退出程序,正常退出是sys.exit(0) sys.exit(0) # sys.version,获取python解释程序的版本信息 print(sys.version)#3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] #sys.platform,返回操作系统平台名称 print(sys.platform)#win32
(5)shutil模块
import shutil #copyfileobj(fsrc,fdst[,length=16*1024]),copy文件内容到另一个文件 f = open("names","r") f_new = open("names2","w") hutil.copyfileobj(f,f_new) #copyfile(src,dst),从源src复制到dst中去,当然前提是目标地址时具备可先权限,抛出的异常信息为IOException, #如果当前的dst已存在的话就会被覆盖掉 shutil.copyfile("names","names1") #copymode(src,dst),仅复制权限,不更改文件内容、组、用户 shutil.copymode("names","names2") #copystat(src,dst),复制所有的状态信息,包括权限,组,用户,时间等 shutil.copystat("names","names2") #copy( src, dst),复制文件的内容以及权限 shutil.copy("names","names2") #copy2( src, dst),在copy上的基础上再复制文件所有的状态信息 shutil.copy2("names","names2") #copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, #ignore_dangling_symlinks=False),递归的复制文件内容及状态信息 shutil.copytree(r"F:\超级下载器",r"F:\m") #shutil.rmtree(path, ignore_errors=False, onerror=None),递归地删除文件 shutil.rmtree(r"F:\m") #make_archive(base_name, format, root_dir=None, base_dir=None, #verbose=0,dry_run=0, owner=None, group=None, logger=None),压缩打包 ''' base_name:压缩打包后地文件名或路径名 format: 压缩或者打包格式 "zip","tar","bztar" or "gztar" root_dir: 在哪个目录或者文件打包(源文件) ''' shutil.make_archive("make_archive_test","zip",r"F:\a")#默认打包到当前目录下
#shutil.move(src, dst) ,递归的移动文件
import shutil
shutil.move("names1","names2")
(6)zipfile模块
zipfile模块用来做zip格式编码的压缩和解压缩的,zipfile里有两个非常重要的class, 分别是ZipFile和ZipInfo,
在绝大多数的情况下,我们只需要使用这两个class就可以了。
ZipFile是主要的类,用来创建和读取zip文件而ZipInfo是存储的zip文件的每个文件的信息的。
一个ZipInfo对象中包含了压缩包内一个文件的信息,
其中比较常用的是 filename, file_size, header_offset, 分别为文件名,文件大小,文件数据在压缩包中的偏移。
import zipfile #ZipFile(filename,"w"),创建一个压缩包 zipfile.ZipFile("day5.zip","w") #把其他的文件压进同一个压缩包 z = zipfile.ZipFile("day5.zip","w") z.write(r"F:\a") z.write("I Found You") #从压缩包里解压缩出一个文件的方法是使用ZipFile的read方法 z = zipfile.ZipFile("day5.zip","r") print(z.namelist())#['I Found You'] print(z.read(z.namelist()[0]).decode(encoding="gbk"))#输出压缩文件地内容 #解压缩 z = zipfile.ZipFile("day5.zip","r") z.extractall()
(7)shelve模块
shelve模块时一个简单的key-value将内存数据通过文件持久化地模块,可以持久化任何pickle可支持地python数据格式。key必须是字符串
写:
import shelve d = shelve.open("shelve_test1") info = {"name":"Mr Wu","age":19} names = ["Mr Wu","Jing Jiu","Na Yue"] d["a"] = info d["b"] = names d.close()
读:
d = shelve.open("shelve_test1") print(d.get("a")) print(d.get("b"))
d.close()
(8)xml模块(我自己的电脑中还未安装相关模块(expat))
xml是实现不同语言或程序设计之间进行数据交换地协议,跟json差不多
创建xml:
import xml.etree.ElementTree as ET new_xml = ET.Element("person_info_list")#生成根节点 person_info = ET.SubElement(new_xml,"personinfo",attrib={"people":"yes"}) name = ET.SubElement(person_info,"name") name.text = "Mr Wu" age = ET.SubElement(person_info,"age") age.text = "19" person_info2 = ET.SubElement(new_xml,"personinfo",attrib={"people":"no"}) name = ET.SubElement(person_info2,"name") name.text = "Alex" age = ET.SubElement(person_info2,"age") age.text = "34" et = ET.ElementTree(new_xml)#生成文档对象 et.write("xml_test.xml",encoding="utf-8",xml_declaration=True)
<?xml version='1.0' encoding='utf-8'?> <person_info_list> <personinfo people="yes"> <name>Mr Wu</name> <age>19</age> </personinfo> <personinfo people="no"> <name>Alex</name> <age>34</age> </personinfo> </person_info_list>
xml处理:
#获取根节点 tree = ET.parse("xml_test.xml") root = tree.getroot() tag = root.tag#根节点的名称 attrib = root.attrib#根节点地属性 print(tag,attrib) #获取子节点的属性和名称 for child in root: print(child.tag,child.attrib) #输出为personinfo {"people":"Yes"} personinfo {"people":"No"} #获取属性对应的值 for personinfo in root.findall("personinfo"): people = personinfo.get("people") name = personinfo.get("name") print(people,name) #输出为:"yes" Mr Wu , "No" "Alex" #遍历xml文档 for child in root: print(child.tag,child.attrib) for i in child: print(i.tag,i.text,i.attrib) #只遍历name结点 for node in root.iter("name"): print(node.tag,node.text)
xml修改:
tree = ET.parse("xml_test.xml") root = tree.getroot() #修改 for age in root.iter("age"): new_age = int(age.text)+1 age.text = str(new_age) age.set("updated","Yes") tree.write("xml_test1.xml") #删除 for personinfo in root.findall("personinfo"): age = int(personinfo.find("age").text) if age>50: root.remove(personinfo) tree.write("xml_test2.xml")
(9).yaml模块:
暂定,还未开始学习
(10).configparser模块
ConfigParser 是Python自带的模块, 用来读写配置文件.
配置文件的格式是: []包含的叫section, section 下有option=value这样的键值
创建:
import configparser #ConfigParser config = configparser.ConfigParser() config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9'} config['bitbucket.org'] = {} config['bitbucket.org']['User'] = 'hg' config['topsecret.server.com'] = {} config['topsecret.server.com']['Host Port'] = '50022' # mutates the parser config['topsecret.server.com']['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)
[DEFAULT] compressionlevel = 9 serveraliveinterval = 45 compression = yes forwardx11 = yes [bitbucket.org] user = hg [topsecret.server.com] host port = 50022 forwardx11 = no
读、修改:
import configparser config = configparser.ConfigParser() config.read("example.ini") print(config.defaults()) #OrderedDict([('compressionlevel', '9'), ('serveraliveinterval', '45'), ('compression', 'yes'), ('forwardx11', 'yes')]) #获取所有的section print(config.sections())#['bitbucket.org', 'topsecret.server.com'] #删除 config.remove_section("bitbucket.org") with open("example.ini","w") as configfile: configfile.write(config) #获取指定的section,指定的option的值 print(config.get("DEFAULT","forwardx11"))#yes #更新指定section, option的值 config.set("DEFAULT","forwardx11","no") #写入指定section, 增加新option的值 config.set("DEFAULT","name","Mr Wu") # 添加新的 section config.add_section("new_section") config.set("new_section","new_optipn","new_value") config.write(open("example.ini","w"))
(11)hashlib模块
hashlib主要提供字符串加密功能,将md5和sha模块整合在了一起,支持md5,sha1,sha256,sha384,sha512等算法
import hashlib #hashlib主要提供字符串加密功能,将md5和sha模块整合在了一起,支持md5,sha1,sha224,sha256,sha384,sha512等算法 string = "Mr Wu12345" #md5 md5 = hashlib.md5() md5.update(string.encode("utf-8")) res = md5.hexdigest() print(res) #sha256 sha256 = hashlib.sha256() sha256.update(string.encode("utf-8")) res = sha256.hexdigest() print(res) #sha384 sha384 = hashlib.sha384() sha384.update(string.encode("utf-8")) res = sha384.hexdigest() print(res) #sha512 sha512 = hashlib.sha512() sha512.update(string.encode("utf-8")) res = sha512.hexdigest() print(res) #以上实验输出结果为: ''' md5:4e41b58bb0be472b6254a5c48d22d6b7 sha256:f6c91cd8153194b6f4da78807367e439bca62ba441faf48f2c5d0f28131c3862 sha384:e39db18a1a59266a1dcc0c710b4be46f4403aab2deeba1d36f5081b1ce8c5eb3c7fee5cea73bd78e41690be9b1113fbc sha512:126b9738409cd4d20bf2310f9f0559d2434bc9ad9eabcad56a72b9f9ece6955d3c7ec14e5b33f35a8f1f809cb769463fbe5704112531d673c9aab426246e5ee8 ''' #注意:hashlib加密的字符串类型为二进制编码,直接加密会报如下错误 sha1 = hashlib.sha1() sha1.update(string) res = sha1.hexdigest() print(res) #TypeError: Unicode-objects must be encoded before hashing #解决方法: sha1.update(string.encode("utf-8")) sha1.update(bytes(string,encoding="utf-8"))
常用方法:
hash.update(arg)更新哈希对象以字符串参数,注意:如果同一个hash对象反复调用该方法,
则m.update(a),m.update(b),等效于m.update(a+b)
m = hashlib.md5() m.update(b"a") res = m.hexdigest() print("第一次a加密",res) m.update(b"b") res = m.hexdigest() print("第二次b加密",res) m1 = hashlib.md5() m1.update(b"b") res = m1.hexdigest() print("b单独加密",res) m2 = hashlib.md5() m2.update(b"ab") res = m2.hexdigest() print("ab单独加密",res) #以上实验结果 ''' 第一次a加密 0cc175b9c0f1b6a831c399e269772661 第二次b加密 187ef4436122d1cc2f40dc2b92f0eba0 b单独加密 92eb5ffee6ae2fec3ad71c777531578f ab单独加密 187ef4436122d1cc2f40dc2b92f0eba0 '''
hash.digest()返回摘要,作为二进制数据字符串值
hash.hexdigest()返回摘要,作为二进制数据字符串值
hash.copy()复制
高级加密:
以上算法虽然厉害,但存在缺陷,即:可以通过撞库反解。所以有必要对加密算法中添加自定义的key再来做加密
import hashlib low = hashlib.md5() low.update(b"Mr Wu") res = low.hexdigest() print("普通加密:",res) high = hashlib.md5(b"12345") high.update(b"Mr Wu") res = high.hexdigest() print("高级加密:",res) #以上实验的结果 ''' 普通加密: 72420ab5c6befd72f79850d4a896d0a7 高级加密: f02884ca74913c058473420eb3a45e34 '''
(12)正则表达式
import re #2.1开始使用re #将正则表达式编译成pattern对象 pattern = re.compile(r"hello") #使用pattern匹配文本,获得匹配结果,无法匹配时将返回None match = pattern.match("hello world") if match: #使用match获得分组信息 print(match.group()) #输出:hello #简写方法: m = re.match(r"hello","hello world!") print(m.group())#hello #2.2match #Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。 m = re.match(r"(\w+) (\w+)(?P<sign>.*)","hello world!") print("m.string:",m.string) print("m.re:",m.re) print("m.pos:",m.pos) print("m.endpos:",m.endpos) print("m.lastindex:",m.lastindex) print("m.lastgroup:",m.lastgroup) print("m.group(1,2):",m.group(1,2)) print("m.groups():",m.groups()) print("m.groupdict():",m.groupdict()) print("m.start(2):",m.start(2)) print("m.end(2):",m.end(2)) print("m.span(2):",m.span(2)) print("m.expand():",m.expand(r'\2 \1\3')) #以上实验的输出结果: ''' m.string: hello world! m.re: re.compile('(\\w+) (\\w+)(?P<sign>.*)') m.pos: 0 m.endpos: 12 m.lastindex: 3 m.lastgroup: sign m.group(1,2): ('hello', 'world') m.groups(): ('hello', 'world', '!') m.groupdict(): {'sign': '!'} m.start(2): 6 m.end(2): 11 m.span(2): (6, 11) m.expand(): world hello! ''' #2.3pattern p = re.compile(r'(\w+) (\w+)(?P<sign>.*)',re.DOTALL) print("p.pattern:",p.pattern) print("p.flags:",p.flags) print("p.groups:",p.groups) print("p.groupindex",p.groupindex) #======output======== ''' p.pattern: (\w+) (\w+)(?P<sign>.*) p.flags: 48 p.groups: 3 p.groupindex {'sign': 3} ''' #实例方法[re模块方法] pattern = re.compile(r'world') match = pattern.match("hello world") print(match)#None match = pattern.search("hello world") print(match.group())#world p = re.compile(r'\d+') print(p.split('sad219bxckjb39dksb3')) #------output------ #['sad', 'bxckjb', 'dksb', ''] print(p.findall("dsakh2139bsdk392fhs3kj3h3")) #------output------ #['2139', '392', '3', '3', '3'] m = p.finditer("sahd3sak32xsfi8dcsk3223sa1") #返回一个顺序访问每一个匹配结果(match对象)的迭代器 for i in m: print(i.group()) #-----output------ #3 32 8 3223 1 #sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]): #使用repl替换string中每一个匹配的子串后返回替换后的字符串。 #当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。 #当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换 #(返回的字符串中不能再引用分组)count用于指定最多替换次数,不指定时全部替换 p = re.compile(r'(\w+) (\w+)') s = "i say, hello world!" print(p.sub(r"\2 \1",s)) #-----output------ #say i, world hello! def func(m): return m.group(1).title() + ' ' + m.group(2).title() print(p.sub(func,s)) #-----output----- #I Say, Hello World!