一、常用子產品
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()
zipfile壓縮解壓縮
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()
tarfile壓縮解壓縮
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資料
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')
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) #列印生成的格式
建立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()
super方法
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()
組合
轉載于:https://www.cnblogs.com/xiaoyu866/p/7354539.html