Python經常使用模塊2

一:hashlib模塊python

算法介紹:算法

Python摘要算法提供常見的md5和sha1算法數據庫

摘要算法又叫哈希算法和散列算法。他經過函數把任意類型數據轉換成固定長度的字符串(一般是16進製表示)windows

摘要算法就是經過摘要函數f()對任意長度的數據data計算出固定長度的摘要digest,目的是爲了發現原始數據是否被人篡改過。安全

注意:****網絡

摘要算法之因此能指出數據是否被篡改過,就是由於摘要函數是一個單向函數,計算f(data)很容易,但經過digest反推data卻很是困難。並且,對原始數據作一個bit的修改,都會致使計算出的摘要徹底不一樣。運維

***********函數

咱們以常見的摘要算法MD5爲例,計算出一個字符串的MD5值:測試

import hashlib
#實例化對象名能夠不是md5,能夠是其餘的如md5_obj
md5=hashlib.md5()
#對函數f()進行實例化
md5.update(b'how to use md5 in python hashlib?')
#導入任意長度的數據,必定是bytes類型
print(md5.hexdigest())
#計算MD5的hexdigest

注意兩點:第一:實例化對象名能夠是任意    第二:傳入數據必須是bytes類型,第三:不能再元字符串加空格等,或作其餘修改。網站

若是字符串長度過長,能夠不能夠分兩次計算?

import hashlib
md5=hashlib.md5()
md5.update(b'how to use md5')
md5.update(b'in python hashlib?')
print(md5.hexdigest())

兩次打印結果爲:

953c047ffa5aad0804aa9dd743ce76c3
953c047ffa5aad0804aa9dd743ce76c3

*********MD5優點:速度快,長度固定***********

MD5是最多見的摘要算法,速度很快,生成結果是固定的128 bit字節,一般用一個32位的16進制字符串表示。另外一種常見的摘要算法是SHA1,調用SHA1和調用MD5徹底相似:

import hashlib
md5=hashlib.sha1()
md5.update(b'how to use md5')
md5.update(b'in python hashlib?')
print(md5.hexdigest())

************SHA1優點:安全,hash值長,可是費時間***************

SHA1的結果是160 bit字節,一般用一個40位的16進制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不過越安全的算法越慢,並且摘要長度更長。

 

摘要算法應用

任何容許用戶登陸的網站都會存儲用戶登陸的用戶名和口令。如何存儲用戶名和口令呢?方法是存到數據庫表中:

name    | password
--------+----------
michael | 123456
bob     | abc999
alice   | alice2008

若是以明文保存用戶口令,若是數據庫泄露,全部用戶的口令就落入黑客的手裏。此外,網站運維人員是能夠訪問數據庫的,也就是能獲取到全部用戶的口令。正確的保存口令的方式是不存儲用戶的明文口令,而是存儲用戶口令的摘要,好比MD5:

ername | password
---------+---------------------------------
michael  | e10adc3949ba59abbe56e057f20f883e
bob      | 878ef96e86145580c38c87f0410ad153
alice    | 99b1c2188db85afee403b1536010c2c9

考慮這麼個狀況,不少用戶喜歡用123456,888888,password這些簡單的口令,因而,黑客能夠事先計算出這些經常使用口令的MD5值,獲得一個反推表:

'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'

這樣,無需破解,只須要對比數據庫的MD5,黑客就得到了使用經常使用口令的用戶帳號。

對於用戶來說,固然不要使用過於簡單的口令。可是,咱們可否在程序設計上對簡單口令增強保護呢?

因爲經常使用口令的MD5值很容易被計算出來,因此,要確保存儲的用戶口令不是那些已經被計算出來的經常使用口

通過Salt處理的MD5口令,只要Salt不被黑客知道,即便用戶輸入簡單口令,也很難經過MD5反推明文口令。

hashlib.md5("salt".encode("utf8"))

可是若是有兩個用戶都使用了相同的簡單口令好比123456,在數據庫中,將存儲兩條相同的MD5值,這說明這兩個用戶的口令是同樣的。有沒有辦法讓使用相同口令的用戶存儲不一樣的MD5呢?

若是假定用戶沒法修改登陸名,就能夠經過把登陸名做爲Salt的一部分來計算MD5,從而實現相同口令的用戶也存儲不一樣的MD5。

摘要算法在不少地方都有普遍的應用。要注意摘要算法不是加密算法,不能用於加密(由於沒法經過摘要反推明文),只能用於防篡改,可是它的單向計算特性決定了能夠在不存儲明文口令的狀況下驗證用戶口令。

 

2: configparser模塊

該模塊適用於配置文件的格式與windowsini文件相似,能夠包含一個或多個節(section),每一個節能夠有多個參數(鍵 = 值)。
建立文件
來看一個好多軟件的常見文檔格式以下:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes

[bitbucket.org]
User = hg

[topsecret.server.com]
Port = 50022
ForwardX11 = no
若是想用python生成一個這樣的文檔怎麼作呢?

import configparser  #導入模塊

config = configparser.ConfigParser()   #實例化

config["DEFAULT"] = {'ServerAliveInterval': '45',  *鍵與值一一對應
#實例化對象取值        'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11': 'yes'
                     }

config['bitbucket.org'] = {'User': 'hg'}  #修改鍵值

config['topsecret.server.com'] = {'Host Port': '50022', 'ForwardX11': 'no'}  

with open('example.ini', 'w') as configfile:   #打開文件 以寫的方式
    config.write(configfile)        #寫入文件句柄

如何查??

查找文件


import configparser

config = configparser.ConfigParser()

# ---------------------------查找文件內容,基於字典的形式

print(config.sections())  # []

config.read('example.ini')

print(config.sections())  # ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config)  # False
print('bitbucket.org' in config)  # True

print(config['bitbucket.org']["user"])  # hg

print(config['DEFAULT']['Compression'])  # yes

print(config['topsecret.server.com']['ForwardX11'])  # no

print(config['bitbucket.org'])  # <Section: bitbucket.org>

for key in config['bitbucket.org']:  # 注意,有default會默認default的鍵
    print(key)

print(config.options('bitbucket.org'))  # 同for循環,找到'bitbucket.org'下全部鍵

print(config.items('bitbucket.org'))  # 找到'bitbucket.org'下全部鍵值對

print(config.get('bitbucket.org', 'compression'))  # yes       get方法Section下的key對應的value

增刪改呢:

增刪改操做


import configparser

config = configparser.ConfigParser()

config.read('example.ini')

config.add_section('yuan')   增長

config.remove_section('bitbucket.org')   #刪除
config.remove_option('topsecret.server.com', "forwardx11")

config.set('topsecret.server.com', 'k1', '11111') 修改
config.set('yuan', 'k2', '22222')

config.write(open('new2.ini', "w"))  寫入

3 logging模塊(跟日誌打交道的模塊)

import logging
logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

*******

注意:導入模塊的時候logoing.Ddbug()  必須小寫,傳參數,不能大寫

*******

# 默認狀況下Python的logging模塊將日誌打印到了標準輸出中,且只顯示了大於等於WARNING級別的日誌
# 這說明默認的日誌級別設置爲WARNING(日誌級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG)
# 默認的日誌格式爲日誌級別:Logger名稱:用戶輸出消息。

那麼如何 靈活配置日誌級別,日誌格式,輸出位置????

mport logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='/tmp/test.log',
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

注意:設置等級時候:level=logging.DEBUG

logging.basicConfig()函數中可經過具體參數來更改logging模塊默認行爲,可用參數有:

filename:用指定的文件名建立FiledHandler,這樣日誌會被存儲在指定的文件中。
filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。
format:指定handler使用的日誌顯示格式。
datefmt:指定日期時間格式。
level:設置rootlogger(後邊會講解具體概念)的日誌級別
stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。

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 字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒
%(thread)d 線程ID。可能沒有
%(threadName)s 線程名。可能沒有
%(process)d 進程ID。可能沒有
%(message)s用戶輸出的消息

logger對象配置:

import logging

logger = logging.getLogger()
# 建立一個handler,用於寫入日誌文件
fh = logging.FileHandler('test.log',encoding='utf-8')

# 再建立一個handler,用於輸出到控制檯
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setLevel(logging.DEBUG)

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger對象能夠添加多個fh和ch對象
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

 

小結:

logging模塊:

# logging
# 操做日誌的模塊
# 什麼叫日誌
    # 給用戶看的
        # 用戶的重要行爲
            # 登陸 涉及安全
            # 帳單 錢
    # 給開發和運維和測試人員看的
        # 自測   logging.debug('一些中間結果')
        # 測試   1++++++1
        # 運維
    # 記錄
        # 打印在屏幕上
        # 寫入文件裏
    # logging的優點
        # 格式更加規範
        # 等級更加鮮明

# 簡單的配置用法
# import logging
# logging.basicConfig(level=logging.ERROR,  #
#                     format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
#                     datefmt='%a, %d %b %Y %H:%M:%S',
#                     filename='test.log',
#                     filemode='a')
# logging.debug('debug message')  # 調試
# logging.info('info message')    # 信息
# logging.warning('warning message')  # 警告
# logging.error('error message')      # 錯誤
# logging.critical('critical message')  # 嚴重錯誤

# 使用logger對象的用法
import logging
# 首先建立一個logger對象
logger = logging.getLogger()

#建立一個格式
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 建立一個 文件句柄 控制向哪一個文件中輸出 用什麼格式
fh = logging.FileHandler('test3.log',encoding='utf-8')
fh.setFormatter(fmt)

# 建立一個 屏幕句柄 控制向屏幕輸出 用什麼格式
sh = logging.StreamHandler()
sh.setFormatter(fmt)

# 將logger對象和文件句柄,屏幕句柄綁在一塊兒
logger.addHandler(fh)
logger.addHandler(sh)
logger.setLevel(logging.DEBUG)     # 首先必需要總體對logger進行設置
sh.setLevel(logging.INFO)
fh.setLevel(logging.WARNING)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

hashlib模塊小結:

# 摘要算法
# a = alex3714   ===摘要==>   174692740812ab238919
# alex3714   ===摘要==> 174692740812ab238919

# 登陸  md5  sha
    # 密碼不能使用明文存儲
    # 密文存儲 摘要算法
# 校驗文件一致性   md5
    # 網絡的上傳下載
    # 保證多臺機器狀態的一致

import hashlib
# md5_obj = hashlib.md5()
# # md5算法的對象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法對'alex3714'進行摘要
# res = md5_obj.hexdigest()   # 獲取摘要以後的結果
# print(res,type(res))  #aee949757a2e698417463d47acac93df    32位

# user = input('user : ')
# passwd = input('passwd : ')
# md5_obj = hashlib.md5()
# md5_obj.update(passwd.encode('utf-8'))
# passwd = md5_obj.hexdigest()
# if user == 'alex' and passwd == 'aee949757a2e698417463d47acac93df':
#     print('登錄成功')

# md5_obj = hashlib.sha1()
# # md5算法的對象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法對'alex3714'進行摘要
# res = md5_obj.hexdigest()   # 獲取摘要以後的結果
# print(res)  #8a003668a9c990f15148f9e4046e1410781533b6  40

# 相同的字符串使用相同的算法 在任什麼時候候 獲得的結果都是一致的


# 全世界的md5算法都是同樣的
# 123456  111111
# md5_obj = hashlib.md5()
# md5算法的對象
# md5_obj.update(b'123456')  # 使用md5摘要算法對'alex3714'進行摘要
# res = md5_obj.hexdigest()   # 獲取摘要以後的結果
# print(res,type(res))  #aee949757a2e698417463d47acac93df    32位
# 123456 e10adc3949ba59abbe56e057f20f883e
# 撞庫

# 加鹽
# md5_obj = hashlib.md5('鹽'.encode('utf-8'))
# # md5算法的對象
# md5_obj.update(b'alex3714')  # 使用md5摘要算法對'alex3714'進行摘要
# res = md5_obj.hexdigest()   # 獲取摘要以後的結果
# print(res,type(res))
#aee949757a2e698417463d47acac93df    32位
#0e249b9c16ea1d840ce700587cada978

# 動態加鹽  _ 校園管理系統
# username = 'alex'   # alex alex3714
#                     # egon egon5068
# md5_obj = hashlib.md5(username.encode('utf-8')+'鹽'.encode('utf-8'))
# md5_obj.update(b'alex3714')
# res = md5_obj.hexdigest()
# print(res)

# 校驗文件一致性
# with open('userinfo','rb') as f:
#     md5_obj = hashlib.md5()
#     md5_obj.update(f.read())
#     res = md5_obj.hexdigest()
#     print(res)
#
# with open('userinfo','rb') as f:
#     md5_obj = hashlib.md5()
#     for line in f:
#         md5_obj.update(line)   # update操做能夠在hexdigest以前執行屢次
#                                # 分次對一個長字符串進行摘要
#     res = md5_obj.hexdigest()  # 結果是對整個長字符串的摘要結果
#     print(res)

#56fc9aa78c2dd71d547988b24bec198a

# md5_obj = hashlib.md5()
# md5_obj.update(b'aaabbb')
# res = md5_obj.hexdigest()
# print(res)  #6547436690a26a399603a7096e876a2d
#
# md5_obj = hashlib.md5()
# md5_obj.update(b'aa')
# md5_obj.update(b'abbb')
# res = md5_obj.hexdigest()
# print(res)  #6547436690a26a399603a7096e876a2d

 

練習:

# hashlib
    # 給校園管理系統添加密文登陸的功能
    # 檢驗兩個文件的一致性  md5
        # func(文件a的路徑,文件b的路徑):
            # return TRUR 或者 False

# logging模塊
    # 給校園管理系統添加日誌
    # 建立 刪除 關聯 這種關鍵信息建立日誌

# 重寫附加題
    # 用堆棧思想
相關文章
相關標籤/搜索