1. 程式人生 > >day12-內建模組學習(三)

day12-內建模組學習(三)

我的部落格呀,從以前的預習變成了複習了,複習的東西還沒有寫完,哎

今日目錄

1.序列化模組

2.加密模組

3.包的使用

4.random模組

5.shutil模組

 

開始今日份總結

1.序列化模組

在學習序列化模組之前,對於網路傳輸以及檔案寫入讀取都是採用將列表,字典這些資料型別轉換成字串進行,這樣怎麼說呢,能完成但是有點太low了,看一下以前的儲存方式

dic = {'test':'test1與test2','test2':[1,2,3],'test3':{'a':'test','b':'test'}}
m1 = str(dic)
# with open('test','w',encoding='utf-8')as f1:
# f1.write(m1) with open('test','r',encoding='utf-8')as f2: ret = f2.read() print(eval(ret)) #列印結果和dic的內容是一致的

不過在轉換成可以使用的內容用的eval所以不建議使用,使用eval如果是黑客給的真實病毒,就會直接執行,有太大的風險,一般不使用。這就匯入後面的序列化模組。

網路傳輸:轉換成bytes,位元組

檔案寫入:bytes,str

什麼是序列化

序列化:將資料(資料結構)----->轉換成特殊的字串(用於網路傳輸)

反序列化:將網路傳輸或者是檔案中特殊的字串轉換為原來的資料結構

以下是python中提供的序列化模組

  1.1 json模組

  json 序列化模組   是所有語言通用的一種標準(資料轉化格式)。

  json可以轉化的資料型別有

  # str int bool dict list(tuple)None  注意集合型別是沒辦法轉換的

  json的用法就是倆對四個

  第一對方法:dumps與loads ,與網路傳輸有關

import json

dic ={'a':'bc','b':'cd','c':'ef'}
m1 = json.dumps(dic)#將dic轉換成特殊的字元,這個時候就可以將m1寫入檔案
with open('test','w',encoding='utf-8')as f1: f1.write(m1) # print(m1) d1 = json.loads(m1)#將特殊的字元轉換成原本格式 print(d1)#將轉換後的字串轉換出來

  第二對方法:dump與load方法,與檔案相關

dic ={'a':'bc','b':'cd','c':'ef'}
with open('test','w',encoding='utf-8')as f1:
    json.dump(dic,f1)
print('序列化成功!')#檔案寫入成功

with open('test','r',encoding='utf-8')as f2:   
    d1 = json.load(f2)
    print(d1)#檔案讀取成功

  補充方法:對於dump以及load方法每次只能讀取或者寫入一個物件,這個時候就有點尷尬了,這個時候就只能用第一對方法進行對多個物件進行操作了。

dic1 = {'name': '春哥'}
dic2 = {'name': '子伍'}
dic3 = {'name': '王子'}
dic4 = {'name': '女神'}
with open('test.json','w',encoding='utf-8') as f1:
    f1.write(json.dumps(dic1)+'\n')
    f1.write(json.dumps(dic2)+'\n')
    f1.write(json.dumps(dic3)+'\n')
    print('序列化成功!')
with open('test.json','a',encoding='utf-8')as f1:
    f1.write(json.dumps(dic4))
    print('yy')
with open('test.json','r',encoding='utf-8')as f2:
    for line in f2:
        print(json.loads(line))

json的引數

# s = json.dumps(dic,ensure_ascii=False,sort_keys=True,separators=('|',','))  # 序列化過程
# sort_keys 按鍵排序
# ensure_ascii=False 顯示中文
# separators=('|',',') 設定分隔符 沒有意義

總結:

  • loads與dumps是,對於網路傳輸,對於多個數據寫入檔案
  • load與dumpp是,只能用於單一資料結構寫入檔案
  • 如果字典的key為數字,在dumps和loads會將其轉換為字串

  1.2 pickle模組

  pickle與json一樣是倆對四個用法

  dumps與loads 用於網路傳輸,將資料轉換為bytes型別

dic1 = {'name': '春哥'}
dic2 = {'name': '子伍'}
dic3 = {'name': '王子'}
dic4 = {'name': '女神'}
import pickle
b1 = pickle.dumps(dic1)
print(b1)
m1 = pickle.loads(b1)
print(m1)

  dump與load 用於將多個數據寫入檔案,或者是讀取

with open('test.pkl','wb')as f1:
    pickle.dump(dic1,f1)
    pickle.dump(dic2,f1)
    pickle.dump(dic3,f1)
    pickle.dump(dic4,f1)
with open('test.pkl','rb')as f2:
    ret = pickle.load(f2)
    ret1 = pickle.load(f2)
    ret2= pickle.load(f2)
    ret3= pickle.load(f2)
print(ret,ret1,ret2,ret3)

json與pickle的區別

  • json是多語言共用,通用性較好,適配str,int,dic,list,tuple,bool以及none
  • pickle是python自用的,可以轉換python中的任何資料不過只能寫成bytes型別

  1.3 shelve模組

  他也是python內建可以序列化的模組,不過他只能對檔案進行操作

import shelve

f = shelve.open('shelve_file')
f['key'] ={'a':'bc','b':'de','c':'fg'}#直接對檔案控制代碼操作,可以寫入檔案
f.close()
f = shelve.open('shelve_file')
print(f['key'])
f.close()

  shelve模組預設是不能對檔案進行修改的,只能刪除,增加,如果加入引數就可以修改了

f = shelve.open('shelve_file',writeback=True)#如果想要對shelve檔案進行操作,必須設定writeback為真
f['key']['new_value'] ='the new message'
f.close()
f = shelve.open('shleve_file')
print(f['key'])
f.close()

2.加密模組

加密模組也加摘要演算法,是一堆加密演算法的集合體,一般的用法是給密碼加密或者用作檔案校驗

hashlib:將str型別通過演算法轉換成一串等長度的數字

  • 不同的字串,轉換成數字肯定不同
  • 相同的字串即使在不同的計算機上使用相同的加密方法,轉換成的數字一定相同
  • hashlib加密不可逆,不能破解(如果破解一般都是加鹽)

  2.1 MD5加密

   2.1.1 普通加密

import hashlib
#普通加密
ret = hashlib.md5()
ret.update('abc123'.encode('utf-8'))
print(ret.hexdigest())

ret.update('aaaaaaaaa'.encode('utf-8'))
print(ret.hexdigest())
#結果
e99a18c428cb38d5f260853678922e03
792b419cafa3cca8c85c497ff60910fd
#結果都是等長的字串

   2.1.2 靜態加鹽加密

ret = hashlib.md5('我們來一場轟轟烈烈的測試'.encode('utf-8'))#這裡就是加鹽,對內容加固定的檔案頭
ret.update('abc123'.encode('utf-8'))
print(ret.hexdigest())

   2.1.3動態加鹽加密

user_password = input('請輸入你的密碼>>>').strip()
ret= hashlib.md5(user_password[::-2].encode('utf-8'))#動態加鹽將字串切割,翻轉取值
ret.update(user_password.encode('utf-8'))
print(ret.hexdigest())

   2.1.4 小檔案校驗

一般從網路上獲取到檔案,需要對他進行校驗確定他是否傳輸的檔案一致

def check_md5(file):
    ret = hashlib.md5()
    with open(file,mode ='rb')as f1:
        ret.update(f1.read())
        return ret.hexdigest()
print(check_md5('f1'))
print(check_md5('f2'))
#結果
b302efd21a6dc13ca8cdb584f1ce1613
b302efd21a6dc13ca8cdb584f1ce1613
#對於原檔案如果將內容文字中間加空號或者其他都會變更,所以一般來確認檔案的正確性

   2.1.5大檔案校驗

對於小檔案,直接讀取出來,這樣可行,如果是大檔案呢,一個檔案上T這樣不可能一次性讀出來的,這個時候就需要另外的方式來做校驗

在說明大檔案加密之前有一個測試

#單獨加密
ret = hashlib.md5()
ret.update('真相永遠只有一個!'.encode('utf-8'))
print(ret.hexdigest())

#連續拼接加密
ret1 = hashlib.md5()
ret1.update('真相'.encode('utf-8'))
ret1.update('永遠'.encode('utf-8'))
ret1.update('只有'.encode('utf-8'))
ret1.update('一個!'.encode('utf-8'))
print(ret1.hexdigest())
#結果
e269466c88819a19634e4ce95d1f12ae
e269466c88819a19634e4ce95d1f12ae

這說明將一個字串分開,最後拼接在一起用相同加密的方式得到的結果是一致的。

def check_md5(file):
    ret = hashlib.md5()
    with open(file,mode='rb')as f1:
        while True:
            contect = f1.read(1024)#讀取1024位元組
            if contect:
                ret.update(contect)
            else:
                break
        return ret.hexdigest()
print(check_md5('f1'))
print(check_md5('f2'))
#結果
b302efd21a6dc13ca8cdb584f1ce1613
b302efd21a6dc13ca8cdb584f1ce1613

  2.2 sha加密

  sha的用法其實與md5的用法大同小異,都可以普通加密,帶鹽加密,動態鹽加密,檔案校驗

ret= hashlib.sha1()#不同等級的sha
ret.update('123456'.encode('utf-8'))
print(ret.hexdigest())

ret1 = hashlib.sha256()#不同等級的sha
ret1.update('123456'.encode('utf-8'))
print(ret1.hexdigest())
#結果
7c4a8d09ca3762af61e59520943dc26494f8941b
8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92

就會發現不同等級的sha生成的密碼長度完全不一致

sha與MD5的區別

  • MD5比較通用,加密效率快,安全性相對較差
  • sha系列,演算法更好,安全性根據密碼等級越高,效率低,耗時長

3.包的使用

  3.1 當函式過多了,可以分模組檔案去管理函式,模組檔案過多,需要將模組分類,放在一個一個的資料夾內。這個資料夾就叫做包,這樣會使得組織結構更加清晰合理

當我們匯入一個模組的時候會發生三件事

  1. 建立一個以模組命名的名稱空間
  2. 執行模組程式碼,模組裡面的程式碼會載入在模組名命名的名稱空間的記憶體中
  3. 呼叫模組名的名字必須通過模組名的方式呼叫

包也是模組,他是模組的集合體,匯入一個包也會發生三件事

  1. 建立一個以包的命名的名稱空間
  2. 執行包內__iter__檔案,將__iter__裡面的程式碼塊載入到包名對應的名稱空間
  3. 呼叫包內的名字必須通過包名.的方式去呼叫

想要在此檔案引用 bbb包的m3模組 怎麼做?
第一步 在此檔案 import aaa
第二步:在aaa 的 __init__ 新增 from aaa import bbb
第三步:在bbb 的 __init__ 新增 from aaa.bbb import m3
完成以上三步,那麼我在此執行檔案就可以引用bbb包的m3模組裡面的名字。
aaa.bbb.m3.func3()

# 總結:
#  from a.b import c  .的左邊一定是個包,import 後面一定一個具體的名字
# 包裡面的__init__ 如果想要引用模組必須是 from ....import ... 不能直接 import
# from a.b.c.d import e.f.g  錯誤
# from a.b.c.d import e

  3.2 絕對匯入與相對匯入

絕對匯入:以執行檔案的sys.path為起點開始匯入,稱之為絕對匯入

  • 優點:執行檔案與被匯入的模組都可以使用
  • 缺點:所有的匯入都是以sys.path為起始點,匯入麻煩

相對匯入:參照當前所在檔案的資料夾為起始開始查詢,稱之為相對匯入

  • 符號:.代表當前所在檔案的資料夾,..代表上一級資料夾,…代表上一級上一級的資料夾
  • 優點:匯入更加簡單
  • 缺點:只能在匯入包中的模組才能使用

4.random模組

random就是一個隨機模組

import random
print(random.random())#隨機生成0到1內的小數
print(random.uniform(1,3))#隨機生成1到3內的小數
print(random.randint(1,5))#隨機生成大於等於1,小於等於5的整數
print(random.randrange(1,10,2))#隨機生成1到10內的奇數
print(random.choice(['alex','wusir','日天']))#從列表中隨機選出一個
print(random.sample(['alex','wusir','日天'],2))#從列表中隨機選出多個
li =[1,2,3,4,5]
random.shuffle(li)#隨機排列
print(li)

random的應用

#隨機生成一個五字驗證碼
def get_code():
    code =''
    for i in range(5):
        num = str(random.randrange(10))#隨機生成一個數字
        s = chr(random.randint(97,122))#隨機生成一個小寫字母
        s2 = chr(random.randint(65,90))#隨機生成一個大寫字母
        msg = random.choice([num,s,s2])#從數字,小寫字母,大寫字母中隨機生成一個
        code+=msg
    print(code)

get_code()
#結果就一個五位隨機驗證碼

5.shutil模組

import shutil

shutil.copyfileobj(open('f2','r'),open('f3','w'))#將f2的內容複製到f3
shutil.copyfile('f2','f2.bak')#將f2檔案複製給bak檔案
shutil.copytree('nb','nbb',ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))#複製一個資料夾

import time
import tarfile
# 打包檔案
shutil.make_archive('NB1%s' %time.strftime('%Y-%m-%d'),'gztar',root_dir='NB1')


# 解壓
t = tarfile.open('NB12019-01-10.tar.gz','r')
t.extractall('ttt')
t.close()