類的約束異常處理和MD5與日誌
一.類的約束 首先, 你要清楚. 約束是對類的約束. 比如. 現在. 你是一一個專案目經理理. 然後呢. 你給手手下的人人分活. 張三, 你處理理一一下普通用使用者登入, 李四, 你處理理一一下會員登入, 王五, 你處理理一一下管理理員登入. 那這個時候呢. 他們就開始分別取寫他們的功能了了. 但是呢. 你要知道, 程式設計師不一一定會有那麼好的默契. 很有可能三個人人會寫完全三個不同的方方法. 就比如這樣: class Normal:# 張三, 普通人人登入 def login(self): pass class Member: # 李李四, 會員登入 def denglu(self): pass class Admin:# 王五, 管理理員登入 def login(self): pass # 專案目經理理寫的總入入口口 def login(obj): print("準備驗證碼.......") obj.login() print("進入入主⻚頁.......") denglu.......難受不. 但是好歹歹能用用. 還能湊合. 但是這時. 你這邊要使用用了了. 問題就來了 在python中遇到類似問題有兩種辦法解決 1)提取父父類. 然後在父父類中定義好方方法. 在這個方方法中什什麼都不用用乾乾. 就拋一一個異 常就可以了了. 這樣所有的子子類都必須重寫這個方方法. 否則. 訪問的時候就會報錯 class Base: def login(self): raise Exception("你沒有實現login方方法()") class Normal(Base): def login(self): pass class Member(Base): def denglu(self): pass class Admin(Base): def login(self): pass # 專案目經理理寫的總入入口口 def login(obj): print("準備驗證碼.......") obj.login() print("進入入主⻚頁.......") n = Normal() m = Member() a = Admin() login(n) login(m)# 報錯. login(a) 在執行行行到login(m)的時候程式會報錯. 原因是, 此時訪問的login()是父父類中的方方法. 但是父父 類中的方方法會丟擲一一個異常. 所以報錯. 這樣程式設計師就不得不寫login方方法了了. 從而而對子子類進行行行 了了相應的約束. 注意exception是所有異常的根,我們無無法通過這個異常來判斷出程式是因為什什麼報的錯. 所以. 最好是換一一個比較專業的錯誤資訊. 最好是換成NotImplementError.其含義是. "沒有實現的錯誤" 2)使用用元類來描述父父類. 在元類中給出一一個抽象方方法. 這樣子子類就不得不給出抽象 方方法的具體實現. 也可以起到約束的效果. 第二套方方案: 寫抽象類和抽象方方法. 在python中編寫一一個抽象類比較麻麻煩. 需要引入abc模組中的ABCMeta和 abstractmethod這兩個內容. from abc import ABCMeta, abstractmethod # 類中包含了了抽象方方法. 那此時這個類就是個抽象類. 注意: 抽象類可以有普通方方法 class IGame(metaclass=ABCMeta): # 一一個遊戲到底怎麼玩兒兒? 你能形容? 流程能一一樣麼? @abstractmethod def play(self): pass def turn_off(self): print("破B遊戲不不玩了了, 脫坑了了") class DNFGame(IGame): # 子子類必須實現父父類中的抽象方方法. 否則子子類也是抽象類 def play(self): print("dnf的玩兒兒法") # g = IGame() # 抽象類不不能建立物件 dg = DNFGame() dg.play() 註釋:通過程式碼我們能發現. 這裡裡裡的IGame對DNFGame進行行行了了約束. 換句句話說. 父父類對子子類進 行行行了了約束. from abc import ABCMeta, abstractmethod class Base(metaclass=ABCMeta): @abstractmethod def login(self): pass class Normal(Base): def login(self):pass class Member(Base): def denglu(self): pass def login(self): pass # 這個就沒用用了了 # 子子類對父父類進行行行實現 class Admin(Base): def login(self): pass # 專案目經理理寫的總入入口口 def login(obj): print("準備驗證碼.......") obj.login() print("進入入主⻚頁.......") n = Normal() m = Member() a = Admin() login(n) login(m) login(a) 總結: 約束. 其實就是父父類對子子類進行行行約束. 子子類必須要寫xxx方方法. 在python中約束的 方方式和方方法有兩種: 1. 使用用抽象類和抽象方方法, 由於該方方案來源是java和c#. 所以使用用頻率還是很少的 2. 使用用人人為丟擲異常的方方案. 並且儘量量丟擲的是NotImplementError. 這樣比較專 業, 而而且錯誤比較明確.(推薦) 二.異常處理 指:異常是程式在執行行行過程中產生生的錯誤. def chu(a, b): return a/b ret = chu(10, 0) print(ret) 輸出結果: Traceback (most recent call last): File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 100, in <module> ret = chu(10, 0) File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 98, in chu return a/b ZeroDivisionError: division by zero 這個是除數不能為零,在開發過程中這個資訊需經過處理才能交給客戶 def chu(a, b): return a/b try: ret = chu(10, 0) print(ret) except Exception as e: print("除數不不能是0") 結果: 除數不不能是0 註釋:Exception是所有異常的基類, 也就是異常的跟. 換句句話說. 所有的錯誤都是Exception的子子類物件. 我們看到的 ZeroDivisionError 其實就是Exception的子子類. try: print("各種操作....") except ZeroDivisionError as e: print("除數不不能是0") except FileNotFoundError as e: print("文檔案不不存在") except Exception as e: print("其他錯誤") try: '''操作''' except Exception as e: '''異常的父父類,可以捕獲所有的異常''' else: '''保護不不丟擲異常的程式碼, 當try中無無異常的時候執行行行''' finally: '''最後總是要執行行行我''' def add(a, b): ''' 給我傳遞兩個整數. 我幫你計算兩個數的和 :param :param a: :param :param b: :return :return: ''' if not type(a) == int and not type(b) == int: # 當程式執行行行到這句句話的時候. 整個函式的呼叫用會被中斷. 並向外丟擲一一個異常. raise Exception("不不是整數, 朕不不能幫你搞定這麼複雜的運算.") return a + b # 如果呼叫用方方不不處理理異常. 那產生生的錯誤將會繼續向外拋. 最後就拋給了了用使用者 # add("你好", "我叫賽利利亞") # 如果呼叫用方方處理理了了異常. 那麼錯誤就不不會丟給用使用者. 程式也能正常進行行行 try: add("胡辣湯", "滋滋冒油的大大腰子子") except Exception as e: print("報錯了了. 自自己己處理理去吧") 三.自定義異常 自自定義異常: 非常簡單. 只要你的類繼承了了Exception類. 那你的類就是一一個異常類. # 繼承Exception. 那這個類就是一一個異常類 class GenderError(Exception): pass class Person: def __init__(self, name, gender): self.name = name self.gender = gender def nan_zao_tang_xi_zao(person): if person.gender != "男": raise GenderError("性別不不對. 這裡裡裡是男澡堂子子") p1 = Person("alex", "男") p2 = Person("eggon", "蛋") # nan_zao_tang_xi_zao(p1) # nan_zao_tang_xi_zao(p2) # 報錯. 會丟擲一一個異常: GenderError # 處理理異常 例子一 try: nan_zao_tang_xi_zao(p1) nan_zao_tang_xi_zao(p2) except GenderError as e: print(e) # 性別不不對, 這裡裡裡是男澡堂子子 except Exception as e: print("反正報錯了了") 例子二 import traceback # 繼承Exception. 那這個類就是一一個異常類 class GenderError(Exception): pass class Person: def __init__(self, name, gender): self.name = name self.gender = gender def nan_zao_tang_xi_zao(person): if person.gender != "男": raise GenderError("性別不不對. 這裡裡裡是男澡堂子子") p1 = Person("alex", "男") p2 = Person("eggon", "蛋") # nan_zao_tang_xi_zao(p1) # nan_zao_tang_xi_zao(p2) # 報錯. 會丟擲一一個異常: GenderError # 處理理異常 try: nan_zao_tang_xi_zao(p1) nan_zao_tang_xi_zao(p2) except GenderError as e: val = traceback.format_exc() # 獲取到堆疊資訊 print(e) # 性別不不對. 這裡裡裡是男澡堂子子 print(val) except Exception as e: print("反正報錯了了") 結果: 性別不不對. 這裡裡裡是男澡堂子子 Traceback (most recent call last): File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 155, in <module> nan_zao_tang_xi_zao(p2) File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 144, in nan_zao_tang_xi_zao raise GenderError("性別不不對. 這裡裡裡是男澡堂子子") GenderError: 性別不不對. 這裡裡裡是男澡堂子子 四.MD5加密 MD5是一一種不可逆的加密演算法. 它是可靠的. 並且安全的. 在python import hashlib obj = hashlib.md5() obj.update("alex".encode("utf-8")) # 加密的必須是位元組 miwen = obj.hexdigest() print(miwen)# 534b44a19bf18d20b71ecc4eb77c572f 加鹽就行行行了,在使用用MD5的時候. 給函式的引數傳遞一一個byte即可. import hashlib obj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf") obj.update("alex".encode("utf-8")) # 加密的必須是位元組 miwen = obj.hexdigest() print(miwen)# 99fca4b872fa901aac30c3e952ca786d import hashlib def my_md5(s): obj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf") obj.update(s.encode("utf-8")) # 加密的必須是位元組 miwen = obj.hexdigest() return miwen # alex: 99fca4b872fa901aac30c3e952ca786d username = input("請輸入入用使用者名稱:") password = input("請輸入入密碼:") # 資料儲存的時候. # username: my_md5(password) # 加鹽# 假設現在的用使用者名稱和密碼分別是 # wusir: 99fca4b872fa901aac30c3e952ca786d ==> wusir: alex # 用使用者登入 if username == "wusir" and my_md5(password) == "99fca4b872fa901aac30c3e952ca786d": print("成功") else: print("失敗") 五.日誌 1. 匯入logging模組. 2. 簡單配置一一下logging 3. 出現異常的時候(except). 向日日誌裡裡裡寫錯誤資訊. # filename: 文檔名 # format: 資料的格式化輸出. 最終在日日誌文檔案中的樣子子 # 時間-名稱-級別-模組: 錯誤資訊 # datefmt: 時間的格式 # level: 錯誤的級別權重, 當錯誤的級別權重大大於等於leval的時候才會寫入入文檔案 logging.basicConfig(filename='x1.txt', format='%(asctime)s - %(name)s - %(levelname)s -% (module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=0) # 當前配置表示 10以上的分數會被寫入入文檔案 # CRITICAL = 50 # FATAL = CRITICAL # ERROR = 40 # WARNING = 30 # WARN = WARNING # INFO = 20 # DEBUG = 10 # NOTSET = 0 logging.critical("我是critical") # 50分. 最貴的 logging.error("我是error")# 40分 logging.warning("我是警告") # 警告 30 logging.info("我是基本資訊")# 20 logging.debug("我是除錯")# 10 logging.log(2, "我是自自定義")# 自自定義. 看著給分 class JackError(Exception): pass for i in range(10): try: if i % 3 == 0: raise FileNotFoundError("文檔案不不在啊") elif i % 3 == 1: raise KeyError("鍵錯了了") elif i % 3 == 2: raise JackError("傑克Exception") except FileNotFoundError: val = traceback.format_exc() logging.error(val) except KeyError: val = traceback.format_exc() logging.error(val) except JackError: val = traceback.format_exc() logging.error(val) except Exception: val = traceback.format_exc() logging.error(val) 最後, 如果你係統中想要把日日誌文檔案分開. 比如. 一一個大大專案目, 有兩個子子系統, 那兩個子子系 統要分開記錄日日誌 import logging # 建立一一個操作日日誌的物件logger(依賴FileHandler) file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8') file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - % (levelname)s -%(module)s: %(message)s")) logger1 = logging.Logger('s1', level=logging.ERROR) logger1.addHandler(file_handler) logger1.error('我是A系統')# 再建立一一個操作日日誌的物件logger(依賴FileHandler) file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8') file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")) logger2 = logging.Logger('s2', level=logging.ERROR) logger2.addHandler(file_handler2) logger2.error('我是B系統')
一.類的約束首先, 你要清楚. 約束是對類的約束. 比如. 現在. 你是一一個專案目經理理. 然後呢. 你給手手下的人人分活. 張三, 你處理理一一下普通用使用者登入, 李四, 你處理理一一下會員登入, 王五, 你處理理一一下管理理員登入. 那這個時候呢. 他們就開始分別取寫他們的功能了了. 但是呢. 你要知道, 程式設計師不一一定會有那麼好的默契. 很有可能三個人人會寫完全三個不同的方方法. 就比如這樣:class Normal:# 張三, 普通人人登入 def login(self): passclass Member: # 李李四, 會員登入 def denglu(self): passclass Admin:# 王五, 管理理員登入 def login(self): pass# 專案目經理理寫的總入入口口def login(obj): print("準備驗證碼.......") obj.login() print("進入入主⻚頁.......")denglu.......難受不. 但是好歹歹能用用. 還能湊合. 但是這時. 你這邊要使用用了了. 問題就來了在python中遇到類似問題有兩種辦法解決 1)提取父父類. 然後在父父類中定義好方方法. 在這個方方法中什什麼都不用用乾乾. 就拋一一個異常就可以了了. 這樣所有的子子類都必須重寫這個方方法. 否則. 訪問的時候就會報錯class Base: def login(self): raise Exception("你沒有實現login方方法()")class Normal(Base): def login(self): passclass Member(Base): def denglu(self): passclass Admin(Base): def login(self): pass# 專案目經理理寫的總入入口口def login(obj): print("準備驗證碼.......") obj.login() print("進入入主⻚頁.......")n = Normal()m = Member()a = Admin()login(n)login(m)# 報錯.login(a) 在執行行行到login(m)的時候程式會報錯. 原因是, 此時訪問的login()是父父類中的方方法. 但是父父類中的方方法會丟擲一一個異常. 所以報錯. 這樣程式設計師就不得不寫login方方法了了. 從而而對子子類進行行行了了相應的約束.注意exception是所有異常的根,我們無無法通過這個異常來判斷出程式是因為什什麼報的錯. 所以. 最好是換一一個比較專業的錯誤資訊. 最好是換成NotImplementError.其含義是. "沒有實現的錯誤" 2)使用用元類來描述父父類. 在元類中給出一一個抽象方方法. 這樣子子類就不得不給出抽象方方法的具體實現. 也可以起到約束的效果.第二套方方案: 寫抽象類和抽象方方法.在python中編寫一一個抽象類比較麻麻煩. 需要引入abc模組中的ABCMeta和abstractmethod這兩個內容.from abc import ABCMeta, abstractmethod# 類中包含了了抽象方方法. 那此時這個類就是個抽象類. 注意: 抽象類可以有普通方方法class IGame(metaclass=ABCMeta):# 一一個遊戲到底怎麼玩兒兒? 你能形容? 流程能一一樣麼
try:'''操作'''except Exception as e: '''異常的父父類,可以捕獲所有的異常'''else: '''保護不不丟擲異常的程式碼, 當try中無無異常的時候執行行行'''finally: '''最後總是要執行行行我'''
def add(a, b):'''給我傳遞兩個整數. 我幫你計算兩個數的和:param:param a::param:param b::return:return:'''if not type(a) == int and not type(b) == int: # 當程式執行行行到這句句話的時候. 整個函式的呼叫用會被中斷. 並向外丟擲一一個異常. raise Exception("不不是整數, 朕不不能幫你搞定這麼複雜的運算.")return a + b# 如果呼叫用方方不不處理理異常. 那產生生的錯誤將會繼續向外拋. 最後就拋給了了用使用者# add("你好", "我叫賽利利亞")# 如果呼叫用方方處理理了了異常. 那麼錯誤就不不會丟給用使用者. 程式也能正常進行行行try: add("胡辣湯", "滋滋冒油的大大腰子子")except Exception as e: print("報錯了了. 自自己己處理理去吧")三.自定義異常自自定義異常: 非常簡單. 只要你的類繼承了了Exception類. 那你的類就是一一個異常類.# 繼承Exception. 那這個類就是一一個異常類class GenderError(Exception):passclass Person:def __init__(self, name, gender):self.name = nameself.gender = genderdef nan_zao_tang_xi_zao(person):if person.gender != "男":raise GenderError("性別不不對. 這裡裡裡是男澡堂子子")p1 = Person("alex", "男")p2 = Person("eggon", "蛋")# nan_zao_tang_xi_zao(p1)# nan_zao_tang_xi_zao(p2) # 報錯. 會丟擲一一個異常: GenderError# 處理理異常例子一try: nan_zao_tang_xi_zao(p1) nan_zao_tang_xi_zao(p2)except GenderError as e: print(e) # 性別不不對, 這裡裡裡是男澡堂子子except Exception as e: print("反正報錯了了")例子二import traceback# 繼承Exception. 那這個類就是一一個異常類class GenderError(Exception): passclass Person: def __init__(self, name, gender): self.name = name self.gender = gender def nan_zao_tang_xi_zao(person): if person.gender != "男": raise GenderError("性別不不對. 這裡裡裡是男澡堂子子")p1 = Person("alex", "男")p2 = Person("eggon", "蛋")# nan_zao_tang_xi_zao(p1)# nan_zao_tang_xi_zao(p2) # 報錯. 會丟擲一一個異常: GenderError# 處理理異常try: nan_zao_tang_xi_zao(p1) nan_zao_tang_xi_zao(p2)except GenderError as e: val = traceback.format_exc() # 獲取到堆疊資訊 print(e) # 性別不不對. 這裡裡裡是男澡堂子子 print(val)except Exception as e: print("反正報錯了了")結果:性別不不對. 這裡裡裡是男澡堂子子Traceback (most recent call last):File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 155, in<module>nan_zao_tang_xi_zao(p2)File "/Users/sylar/PycharmProjects/oldboy/面面向物件/day05.py", line 144, innan_zao_tang_xi_zaoraise GenderError("性別不不對. 這裡裡裡是男澡堂子子")GenderError: 性別不不對. 這裡裡裡是男澡堂子子
四.MD5加密MD5是一一種不可逆的加密演算法. 它是可靠的. 並且安全的. 在python
import hashlibobj = hashlib.md5()obj.update("alex".encode("utf-8")) # 加密的必須是位元組miwen = obj.hexdigest()print(miwen)# 534b44a19bf18d20b71ecc4eb77c572f加鹽就行行行了,在使用用MD5的時候. 給函式的引數傳遞一一個byte即可.import hashlibobj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf")obj.update("alex".encode("utf-8")) # 加密的必須是位元組miwen = obj.hexdigest()print(miwen)# 99fca4b872fa901aac30c3e952ca786dimport hashlibdef my_md5(s): obj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf") obj.update(s.encode("utf-8")) # 加密的必須是位元組 miwen = obj.hexdigest() return miwen# alex: 99fca4b872fa901aac30c3e952ca786dusername = input("請輸入入用使用者名稱:")password = input("請輸入入密碼:")# 資料儲存的時候.# username: my_md5(password)# 加鹽# 假設現在的用使用者名稱和密碼分別是# wusir: 99fca4b872fa901aac30c3e952ca786d==> wusir: alex# 用使用者登入if username == "wusir" and my_md5(password) =="99fca4b872fa901aac30c3e952ca786d": print("成功")else: print("失敗")
五.日誌1. 匯入logging模組.2. 簡單配置一一下logging3. 出現異常的時候(except). 向日日誌裡裡裡寫錯誤資訊.
# filename: 文檔名# format: 資料的格式化輸出. 最終在日日誌文檔案中的樣子子#時間-名稱-級別-模組: 錯誤資訊# datefmt: 時間的格式# level: 錯誤的級別權重, 當錯誤的級別權重大大於等於leval的時候才會寫入入文檔案logging.basicConfig(filename='x1.txt',format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',datefmt='%Y-%m-%d %H:%M:%S',level=0) # 當前配置表示 10以上的分數會被寫入入文檔案# CRITICAL = 50# FATAL = CRITICAL# ERROR = 40# WARNING = 30# WARN = WARNING# INFO = 20# DEBUG = 10# NOTSET = 0logging.critical("我是critical") # 50分. 最貴的logging.error("我是error")# 40分logging.warning("我是警告")# 警告 30logging.info("我是基本資訊")# 20logging.debug("我是除錯")# 10logging.log(2, "我是自自定義")# 自自定義. 看著給分class JackError(Exception):passfor i in range(10): try: if i % 3 == 0: raise FileNotFoundError("文檔案不不在啊") elif i % 3 == 1: raise KeyError("鍵錯了了") elif i % 3 == 2: raise JackError("傑克Exception") except FileNotFoundError: val = traceback.format_exc() logging.error(val) except KeyError: val = traceback.format_exc() logging.error(val) except JackError: val = traceback.format_exc() logging.error(val) except Exception: val = traceback.format_exc() logging.error(val)
最後, 如果你係統中想要把日日誌文檔案分開. 比如. 一一個大大專案目, 有兩個子子系統, 那兩個子子系統要分開記錄日日誌import logging# 建立一一個操作日日誌的物件logger(依賴FileHandler)file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s"))logger1 = logging.Logger('s1', level=logging.ERROR)logger1.addHandler(file_handler)logger1.error('我是A系統')# 再建立一一個操作日日誌的物件logger(依賴FileHandler)file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')file_handler2.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))logger2 = logging.Logger('s2', level=logging.ERROR)logger2.addHandler(file_handler2)logger2.error('我是B系統')