python学习之路-day7
一、常用模块
shutil
xml
configparser
hashlib
subprocess
1、shutil模块
用途:高级的文件、文件夹、压缩包处理模块
shutil.copyfileobj(fsrc,fdst[,length])
将文件内容拷贝到另一个文件中
1 import shutil 2 shutil.copyfileobj(open('old.xml','r'),open('new.xml','w'))
shutil.copyfile(src,dst)
拷贝文件
til.copyfile('haha.log','xixi.log') #目标文件无需存在
shutil.copymode(src,dst)
仅拷贝权限。内容、组、用户均不变
shutil.copymode('haha.log','xixi.log') #目标文件必须存在
shutil.copystat(src,dst)
仅拷贝状态的信息,包括:mode bits,atime,mtime,flags
shutil.copystat('haha.log','xixi.log') #目标文件必须存在
shutil.copy(src,dst)
拷贝文件和权限
shutil.copy('haha.log','xixi.log')
shutil.copy2(src,dst)
拷贝文件和状态信息
shutil.copy2('haha.log','xixi.log')
shutil.ignore_patterns(*patterns)
shutil.copytree(src,dst,symlinks=False,ignore=None)
递归的去拷贝文件夹
shutil.copytree('old_dir','new_dir',ignore=shutil.ignore_patterns('*.pyc','tmp*')) #目标目录不能存在,注意对new_dir目录父目录要有可写权限,ignore的意思是排除

shutil.copytree('f1','f2',symlinks=True,ignore=shutil.ignore_patterns('*.pyc','tmp*')) #通常对的拷贝都把软链接拷贝成硬链接,即对待软链接来说,创建新的文件
shutil.rmtree(path[,ignore_errors[,onerror]])
递归的去删除文件
shutil.rmtree('old_dir')
shutil.move(src,dst)
递归的去移动文件,它类似mv命令,其实就是重命名
shutil.move('old_file','new_file')
shutil.make_archive(base_name,format,...)
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
#将 /data下的文件打包放置当前程序目录 ret = shutil.make_archive('data_bak','gztar',root_dir='/data') #将 /data下的文件打包放置 /tmp/目录 ret = shutil.make_archive('/tmp/data_bak','gztar',root_dir='/data')

import zipfile #压缩 z = zipfile.ZipFile('access_log.zip','w') z.write('a.log') z.write('data.data') z.close() #解压 z = zipfile.ZipFile('access_log.zip','r') z.extractall(path='.') z.close()

import tarfile #压缩 t = tarfile.open('/tmp/data.tar','w') t.add('/test1/a.py',arcname='a.bak') t.add('/test1/b.py',arcname='b.bak') t.close() #解压 t = tarfile.open('/tmp/data.tar','r') t.extractall('/data') t.close()
2、xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,在json还没诞生的黑暗年代,大家只能选择使用xml,至今很多传统公司如金融行业的很多系统的接口还主要是xml
xml的格式如下,就是通过<>节点来区别数据结构的

<data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> <egon age="18">hello</egon></country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> <egon age="18">hello</egon></country> <country name="Panama"> <year>2011</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> <egon age="18">hello</egon></country> </data>
xml协议在各个语言里都是支持的,在python中可以用以下模块操作xml:
print(root.iter('year')) #全文搜索 print(root.find('country')) #在root的子节点找,只找一个 print(root.findall('country')) #在root的子节点找,找所有

import xml.etree.ElementTree as ET tree = ET.parse('a.xml') root = tree.getroot() print(root.tag) #遍历xml文档 for child in root: print('====>',child.tag,child.attrib,child.attrib['name']) for i in child: print(i.tag,i.attrib,i.text) #只遍历year节点 for node in root.iter('year'): print(node.tag,node.text) #增加node for country in root.iter('country'): e = ET.Element('xiaoyu') e.text = 'hello' e.attrib = {'age':'18'} country.append(e) tree.write('a.xml') #删除node for country in root.iter('country'): print(country.tag) rank = country.find('rank') if int(rank.text) > 10: country.remove(rank) tree.write('a.xml') #修改node for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) node.set('updated','yes') node.set('version','1.0') tree.write('a.xml')

import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
3、configparser模块

# 注释1 ; 注释2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 = v1
读操作
import configparser config=configparser.ConfigParser() config.read('a.cfg') #查看所有的标题 res=config.sections() #['section1', 'section2'] print(res) #查看标题section1下所有key=value的key options=config.options('section1') print(options) #['k1', 'k2', 'user', 'age', 'is_admin', 'salary'] #查看标题section1下所有key=value的(key,value)格式 item_list=config.items('section1') print(item_list) #[('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')] #查看标题section1下user的值=>字符串格式 val=config.get('section1','user') print(val) #egon #查看标题section1下age的值=>整数格式 val1=config.getint('section1','age') print(val1) #18 #查看标题section1下is_admin的值=>布尔值格式 val2=config.getboolean('section1','is_admin') print(val2) #True #查看标题section1下salary的值=>浮点型格式 val3=config.getfloat('section1','salary') print(val3) #31.0
修改操作
import configparser config=configparser.ConfigParser() config.read('a.cfg') #删除整个标题section2 config.remove_section('section2') #删除标题section1下的某个k1和k2 config.remove_option('section1','k1') config.remove_option('section1','k2') #判断是否存在某个标题 print(config.has_section('section1')) #判断标题section1下是否有user print(config.has_option('section1','')) #添加一个标题 config.add_section('egon') #在标题egon下添加name=egon,age=18的配置 config.set('egon','name','egon') config.set('egon','age',18) #报错,必须是字符串 #最后将修改的内容写入文件,完成最终的修改 config.write(open('a.cfg','w'))
4、hashlib模块
hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
import hashlib m = hashlib.md5() m.update('hello'.encode('utf-8')) print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 m.update('haha'.encode('utf-8')) print(m.hexdigest()) #ab540ca02784f1e2f0fb8e1d2d1d92a9 m2 = hashlib.md5() m2.update('hellohaha'.encode('utf-8')) print(m2.hexdigest()) #ab540ca02784f1e2f0fb8e1d2d1d92a9 ''' 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样 但是update多次为校验大文件提供了可能。 '''
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
import hashlib # ######## 256 ######## hash = hashlib.sha256('898oaFs09f'.encode('utf8')) hash.update('alvin'.encode('utf8')) print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7

import hashlib passwds=[ 'alex3714', 'alex1313', 'alex94139413', 'alex123456', '123456alex', 'a123lex', ] def make_passwd_dic(passwds): dic={} for passwd in passwds: m=hashlib.md5() m.update(passwd.encode('utf-8')) dic[passwd]=m.hexdigest() return dic def break_code(cryptograph,passwd_dic): for k,v in passwd_dic.items(): if v == cryptograph: print('密码是===>\033[46m%s\033[0m' %k) cryptograph='aee949757a2e698417463d47acac93df' break_code(cryptograph,make_passwd_dic(passwds))
python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 进行进一步的处理然后再加密:
import hmac 2 h = hmac.new('alvin'.encode('utf8')) #加盐 3 h.update('hello'.encode('utf8')) 4 print (h.hexdigest())#320df9832eab4c038b6c1d7ed73a5940

#要想保证hmac最终结果一致,必须保证: #1:hmac.new括号内指定的初始key一样 #2:无论update多少次,校验的内容累加到一起是一样的内容 import hmac h1=hmac.new(b'egon') h1.update(b'hello') h1.update(b'world') print(h1.hexdigest()) h2=hmac.new(b'egon') h2.update(b'helloworld') print(h2.hexdigest()) h3=hmac.new(b'egonhelloworld') print(h3.hexdigest()) ''' f1bf38d054691688f89dcd34ac3c27f2 f1bf38d054691688f89dcd34ac3c27f2 bcca84edd9eeb86f30539922b28f3981 '''
5、subprocess模块
import subprocess ''' sh-3.2# ls /Users/egon/Desktop |grep txt$ mysql.txt tt.txt 事物.txt ''' res1=subprocess.Popen('ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout, stdout=subprocess.PIPE) print(res.stdout.read().decode('utf-8')) #等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep res1=subprocess.Popen('ls /Users/jieli/Desktop |grep txt$',shell=True,stdout=subprocess.PIPE) print(res1.stdout.read().decode('utf-8')) #windows下: # dir | findstr 'test*' # dir | findstr 'txt$' import subprocess res1=subprocess.Popen(r'dir C:\Users\Administrator\PycharmProjects\test\函数备课',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('findstr test*',shell=True,stdin=res1.stdout, stdout=subprocess.PIPE) print(res.stdout.read().decode('gbk')) #subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码
二、面向对象
1、面向对象与面向过程的区别:
面向过程:核心是过程二字,过程指的是问题的解决步骤,即先干什么再干什么,基于面向过程去设计程序就好比在设计一条流水线,是一种机械式的思维方式
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差
应用:脚本程序,比如linux系统管理脚本,著名案例:linux内核、httpd、git
面向对象 :核心是对象二字,对象就是特征与技能的结合体,如果把设计程序比喻成创造一个世界,那你就是这个世界的上帝,与面向过程对机械流水的模拟形成鲜明的对比,面向对象更加注重的对现实时间的模拟
优点:可扩展性
缺点:
类即种类,类别,对象是特种和技能的结合体,那么类就是一系列对象相似的特征与技能的结合体
在现实世界中:先有一个个具体存在的对象
在程序中:一定是先定义类,后调用类来产生对象

1 class OldboyStudent: 2 school = 'oldboy' #类的数据属性 3 def learn(self): #类的函数属性 4 print('is learning') 5 6 def eat(self): 7 print('is eating') 8 #类体的代码在类定义阶段就会执行,理所当然会产生类的名称空间,用_dict_属性查看 9 print(OldboyStudent.__dict__) 10 print(OldboyStudent.__dict__['school']) 11 print(OldboyStudent.__dict__['learn']) 12 13 #类的属性操作 14 print(OldboyStudent.school) 15 print(OldboyStudent.learn) 16 OldboyStudent.x = 1111111111111 17 OldboyStudent.school = 'Oldboy' 18 del OldboyStudent.school 19 print(OldboyStudent.__dict__) 20 OldboyStudent.__dict__['x'] = 111111111 #类的属性无法用字典方式修改
产生程序中的对象:类名加括号,调用类,产生一个该类的实际存在的对象,该调用过程称为实例化,产生的结果又可以称为实例化对象
class OldboyStudent: school = 'oldboy' count = 0 def __init__(self,age,name,sex): #在实例化时,产生对象之后执行 self.age = age self.name = name self.sex = sex def learn(self): print('%s is learning' %self.name) obj1 = OldboyStudent(20,'小雨','male') #分两步: #第一步:产生一个空对象obj1 #第二步:OldboyStudent.__init__(obj1,20,'小雨','male') print(obj1.__dict__) OldboyStudent.learn(obj1) obj1.learn() #等同于OldboyStudent.learn(obj1) obj1.name = '哈哈' #对象可以通过__dict__修改私有属性 obj1.__dict__.pop('name')
2、继承:
指的是类与类之间的关系,是一种什么是什么的关系,功能之一就是用来解决代码重用的问题。继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
继承分为单继承和多继承:
class ParentClass1: pass class ParentClass2: pass class SubClass1(ParentClass1): pass class SubClass2(ParentClass1,ParentClass2): pass print(SubClass1.__bases__) #会以元组形式展示父类 print(SubClass2.__bases__)
在子类派生出的新的方法内重用父类的功能方式:指名道姓法
OldboyPeople.__init__ 这种调用方式本身与继承是没有关系的

class OldboyPeople: school = 'oldboy' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print('is eating') class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex,course): super().__init__(name,age,sex) self.course = course def tell_info(self): print('%s 选择了 %s课程' %(self.name,self.course)) yu_obj = OldboyStudent('xiaoyu',18,'male','Python') yu_obj.tell_info()

class OldboyPeople: school = 'oldboy' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print('is eating') class OldboyStudent(OldboyPeople): def __init__(self,name,age,sex): OldboyPeople.__init__(self,name,age,sex) def learn(self): print('%s is learning' %self.name) class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,salary,title): OldboyPeople.__init__(self,name,age,sex) self.salary = salary self.title = title self.course = [] def teach(self): print('%s is teaching' %self.name) class Course: def __init__(self,course_name,course_period,course_price): self.course_name = course_name self.course_period = course_period self.course_price = course_price def tell_info(self): print('<课程名:%s 周期:%s 价格:%s>' %(self.course_name,self.course_period,self.course_price)) python = Course('Python','6mons',3000) linux = Course('Linux','3mons',2000) bigdata = Course('Bigdata','1mons',1000) xy_obj = OldboyStudent('xiaoyu',18,'male') egon_obj = OldboyTeacher('egon',28,'male',3.1,'沙河一霸') egon_obj.course.append(linux) egon_obj.course.append(python) for i in egon_obj.course: i.tell_info()