mail_helper.py是郵件操做包,用來發送郵件的。html
1 #!/usr/bin/evn python 2 # coding=utf-8 3 4 import smtplib 5 from email.mime.text import MIMEText 6 from traceback import format_exc 7 from config import const 8 9 # 初始化郵件參數 10 smtp = const.SMTP 11 port = const.PORT 12 user = const.EMAIL_USER 13 passwd = const.EMAIL_PWD 14 email_list = const.EMAIL_LIST 15 err_title = const.EMAIL_ERR_TITLE 16 17 18 def send_mail(subject, context, to_list): 19 ''' 20 發送郵件 21 接收參數: 22 subject 郵件主題 23 context 郵件內容 24 to_list 接收者郵件列表,每一個郵件地址用","分隔 25 ''' 26 if not subject or not context or not to_list: 27 return '郵件發送失敗,郵件主題、內容與收件人郵件都是必填項' 28 29 # 初始始化郵件相關參數 30 email = MIMEText(context, 'html', 'utf-8') 31 email['To'] = to_list 32 email['Subject'] = subject 33 email['From'] = user 34 35 # QQ郵箱改成ssl方式發送了 36 # s = smtplib.SMTP(smtp) 37 s = smtplib.SMTP_SSL(smtp) 38 try: 39 s.login(user, passwd) 40 s.sendmail(user, email_list, email.as_string()) 41 s.close() 42 return None 43 except Exception as e: 44 s.close() 45 stacktrace = format_exc() 46 return '郵件發送失敗,出現異常:' + str(e.args) + stacktrace + '\n' 47 48 49 def send_error_mail(context): 50 ''' 51 發送郵件 52 接收參數: 53 context 郵件內容 54 ''' 55 if not context: 56 return '郵件內容是必填項' 57 58 send_mail(err_title, context, email_list)
send_mail()函數只須要提交郵件標題、內容和收件人列表,就能夠將郵件發送出去,使用的發件人是前面配置const.py裏設置的賬號,若是沒有在配置裏設置好對應的帳號密碼,郵件將會發送不成功。python
send_error_mail()函數是用來發送異常日誌信息的,它默認是給log_helper.py裏的異常日誌記錄函數error()調用,這樣當代碼執行時出現異常,咱們第一時間就會收到這封異常郵件,而後能夠針對性的去進行處理。固然若是服務器出現故障時,有可能會一會兒收到很是多的郵件,被郵件服務器封掉IP的。因此通常我都會用本身的郵箱給本身發,這樣萬一給封了IP仍是能夠收到發送不成功的郵件的。另外,前面說過,api文件夾裏的__init__.py和其餘文件夾的這個文件有點不同,你們能夠對比一下,它會幫咱們解決不少很基本的問題,特別是更新線上代碼時,有時會忘記提交新建的python文件,而這個文件又被其它文件所調用,這時python初始化就會發生異常,第一時間咱們就會收到提醒郵件,避免線上服務掛了也不知道的狀況發生。api
send_error_mail()函數的郵件標題能夠在const.py配置中進行設置(見下面參數),通常我會分開發、測試、預生產、生產等標題,這樣在收到郵件時方便咱們區分是那一個環境出現了故障服務器
### 郵件服務參數 ### # 郵件服務器 SMTP = 'smtp.qq.com' # 郵件服務器端口 PORT = 465 # email發送帳號 EMAIL_USER = 'xxxxxx@qq.com' # email發送密碼 EMAIL_PWD = 'xxxxxxxxxxxxxxxxx' # 系統異常郵件通知地址,多個地址用逗號分隔 EMAIL_LIST = 'xxxxxx@qq.com' # 異常郵件通知標題 # ——因爲咱們有開發環境、測試環境、預生產環境、生產環境等多個不一樣的環境, # ——因此在發送異常通知時若是區分的話,可能就弄不清是那個環境出了問題, # ——咱們能夠經過設置郵件標題爲:開發、測試、預生產、生產等標籤來方便區分是那個環境發送的異常通知 EMAIL_ERR_TITLE = '系統異常通知-simple-開發'
測試用例:dom
#!/usr/bin/evn python # coding=utf-8 import unittest from common import mail_helper, except_helper class MailHelperTest(unittest.TestCase): """郵件操做包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') def tearDown(self): """清理測試環境""" print('------clear------') def test(self): mail_helper.send_mail('test', 'test', '1654937@qq.com') except_info = except_helper.detailtrace() mail_helper.send_error_mail('出現異常,堆棧信息:' + except_info) if __name__ == '__main__': unittest.main()
執行結果:ide
log_helper.py是日誌操做包函數
1 #!/usr/bin/evn python 2 # coding=utf-8 3 4 import logging 5 import logging.handlers 6 import traceback 7 8 from common import mail_helper, except_helper 9 10 11 def info(content): 12 """記錄日誌信息""" 13 if content: 14 logging.info(content) 15 16 def error(content = '', is_send_mail = True): 17 """記錄錯誤日誌信息""" 18 if traceback: 19 content = content + '\n' + traceback.format_exc() + '\n' 20 # 獲取程序當前運行的堆棧信息 21 detailtrace = except_helper.detailtrace() 22 content = content + '程序調用堆棧的日誌:' + detailtrace + '\n' 23 24 logging.info(content) 25 26 # 發送郵件通知相關人員 27 if is_send_mail: 28 info = mail_helper.send_error_mail(context=content) 29 if info: logging.info(info)
info()函數用於記錄程序執行過程當中的一些信息,好比與第三方接口(最多見的是支付接口)通信時,將提交的網址、參數和返回的結果記錄下來,方便咱們在須要時查看,排查出錯問題;好比咱們須要排查生產環境異常,定位錯誤信息位置時,在相關代碼中間添加,而後將相關數據變量值記錄下來,幫助咱們定位問題所在......測試
error()函數除了擁有info()函數的功能外,它在記錄信息的同時,還會自動發送一封郵件到咱們的郵箱。經過它放在try...except...中。ui
#!/usr/bin/evn python # coding=utf-8 import logging import os import unittest from common import log_helper class LogHelperTest(unittest.TestCase): """日誌操做包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') # 獲取本腳本所在的上級路徑(由於log_helper_text.py是在test目錄下面,並不在根目錄,而咱們想將日誌都記錄在根據目錄下的log目錄裏,因此須要獲取test的上級目錄) program_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 初始化日誌目錄 log_path = os.path.join(program_path, 'log') # 當日志目錄不存在時建立日誌目錄 if not os.path.exists(log_path): os.mkdir(log_path) # 定義日誌輸出格式 logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', filename="%s/info.log" % log_path, filemode='a') def tearDown(self): """清理測試環境""" print('------clear------') def test(self): log_helper.info('記錄代碼執行的相關記錄或信息') try: result = '0' / 10 except Exception as e: log_helper.error('出現異常:' + str(e.args)) if __name__ == '__main__': unittest.main()
執行結果:spa
random_helper.py是隨機數操做包,經過裏面的函數,咱們能夠方便快捷的獲取指定大小範圍的數值型隨機數;指定長度的數字、大小寫字母、數字與字母混合型隨機數;獲取uuid隨機碼。
1 #!/usr/bin/evn python 2 # coding=utf-8 3 4 import random 5 import uuid 6 from common import encrypt_helper 7 8 ### 定義常量 ### 9 # 小寫字母 10 lowercase_letters = "abcdefghijklmnopqrstuvwxyz" 11 # 大寫字母 12 majuscule = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 13 # 數字 14 numbers = "0123456789" 15 ################ 16 17 def ___get_randoms(length, text): 18 """ 19 內部函數,獲取指定長度的隨機字符 20 :param length: 將要生成的字符長度 21 :param text: 生成隨機字符的字符池 22 :return: 生成好的隨機字符串 23 """ 24 return random.sample(text, length) 25 26 def get_number(length): 27 """ 28 獲取指定長度的數字,類型是字符串 29 :param length: 將要生成的字符長度 30 :return: 生成好的隨機字符串 31 """ 32 return ''.join(___get_randoms(length, numbers)) 33 34 def get_number_for_range(small, max): 35 """ 36 獲取指定大小的整形數值 37 :param small: 最小數值 38 :param max: 最大數值 39 :return: 生成好的隨機數值 40 """ 41 return random.randint(small, max) 42 43 def get_string(length): 44 """ 45 獲取指定長度的字符串(大小寫英文字母+數字) 46 :param length: 將要生成的字符長度 47 :return: 生成好的隨機字符串 48 """ 49 return ''.join(___get_randoms(length, lowercase_letters + majuscule + numbers)) 50 51 def get_letters(length): 52 """ 53 生成隨機英文字母字符串(大小寫英文字母) 54 :param length: 將要生成的字符長度 55 :return: 生成好的隨機字符串 56 """ 57 return ''.join(___get_randoms(length, lowercase_letters + majuscule)) 58 59 def get_uuid(): 60 """ 61 隨機生成uuid 62 :return: 生成好的uuid 63 """ 64 return str(uuid.uuid4()).replace('-', '')
由於比較簡單,因此不一一說明,直接看測試用例
#!/usr/bin/evn python # coding=utf-8 import unittest from common import random_helper class RandomHelperTest(unittest.TestCase): """隨機數操做包測試類""" def setUp(self): """初始化測試環境""" print('------ini------') def tearDown(self): """清理測試環境""" print('------clear------') def test(self): print('獲取0到100之間的隨機數') print(random_helper.get_number_for_range(0, 100)) print(random_helper.get_number_for_range(0, 100)) print('獲取長度爲5的數字隨機碼') print(random_helper.get_number(5)) print(random_helper.get_number(5)) print('獲取長度爲6的英文隨機碼') print(random_helper.get_letters(6)) print(random_helper.get_letters(6)) print('獲取長度爲6的數字與英文隨機碼') print(random_helper.get_string(6)) print(random_helper.get_string(6)) print('獲取uuid') print(random_helper.get_uuid()) print(random_helper.get_uuid()) if __name__ == '__main__': unittest.main()
執行結果:
------ini------ 獲取0到100之間的隨機數 54 21 獲取長度爲5的數字隨機碼 20156 58132 獲取長度爲6的英文隨機碼 BqQCZP ybFIaB 獲取長度爲6的數字與英文隨機碼 FZfEgd GAslRy 獲取uuid 2aba0e946414434ea6b7f2e425d8b41b 52fe4545b09443a088ce460453d909fa ------clear------
版權聲明:本文原創發表於 博客園,做者爲 AllEmpty 本文歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然視爲侵權。
python開發QQ羣:669058475(本羣已滿)、733466321(能夠加2羣) 做者博客:http://www.cnblogs.com/EmptyFS/