zoukankan      html  css  js  c++  java
  • 我的第一个python web开发框架(12)——工具函数包说明(三)

      mail_helper.py是邮件操作包,用来发送邮件的。

     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 + '
    '
    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)
    View Code

      send_mail()函数只需要提交邮件标题、内容和收件人列表,就可以将邮件发送出去,使用的发件人是前面配置const.py里设置的帐号,如果没有在配置里设置好对应的账号密码,邮件将会发送不成功。

      send_error_mail()函数是用来发送异常日志信息的,它默认是给log_helper.py里的异常日志记录函数error()调用,这样当代码执行时出现异常,我们第一时间就会收到这封异常邮件,然后可以针对性的去进行处理。当然如果服务器出现故障时,有可能会一下子收到非常多的邮件,被邮件服务器封掉IP的。所以一般我都会用自己的邮箱给自己发,这样万一给封了IP还是可以收到发送不成功的邮件的。另外,前面说过,api文件夹里的__init__.py和其他文件夹的这个文件有点不一样,大家可以对比一下,它会帮我们解决很多很基本的问题,特别是更新线上代码时,有时会忘记提交新建的python文件,而这个文件又被其它文件所调用,这时python初始化就会发生异常,第一时间我们就会收到提醒邮件,避免线上服务挂了也不知道的情况发生。

      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-开发'

      测试用例:

    #!/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()

      执行结果:

      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 + '
    ' + traceback.format_exc() + '
    '
    20     # 获取程序当前运行的堆栈信息
    21     detailtrace = except_helper.detailtrace()
    22     content = content + '程序调用堆栈的日志:' + detailtrace + '
    '
    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)
    View Code

      info()函数用于记录程序执行过程中的一些信息,比如与第三方接口(最常见的是支付接口)通讯时,将提交的网址、参数和返回的结果记录下来,方便我们在需要时查看,排查出错问题;比如我们需要排查生产环境异常,定位错误信息位置时,在相关代码中间添加,然后将相关数据变量值记录下来,帮助我们定位问题所在......

      error()函数除了拥有info()函数的功能外,它在记录信息的同时,还会自动发送一封邮件到我们的邮箱。通过它放在try...except...中。

    #!/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()

      执行结果:

      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('-', '')
    View Code

      因为比较简单,所以不一一说明,直接看测试用例

    #!/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/

  • 相关阅读:
    poj 3243 Clever Y(BabyStep GiantStep)
    poj 2417 Discrete Logging
    poj 3481 Double Queue
    hdu 4046 Panda
    hdu 2896 病毒侵袭
    poj 1442 Black Box
    hdu 2815 Mod Tree
    hdu 3065 病毒侵袭持续中
    hdu 1576 A/B
    所有控件
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/7682815.html
Copyright © 2011-2022 走看看