• 我的第一个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/

  • 相关阅读:
    vcsa7.0可能不兼容esxi6.7
    使用livecd 更改root密码
    虚拟机初始化脚本
    一句话修改UUID
    vcsa 6.7 u1升级6.7 u2--6.7U3---6.7U3c
    【转载】:FreeRadius安装及与openldap的连接(centos 7 环境)
    freeradius 关联LDAP认证-按属性过滤LDAP目录中的用户
    使用包ldap3进行Python的LDAP操作
    2020年1月29日-学习flask第一天
    Python-xlwt库的基本使用
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/7682815.html
Copyright © 2020-2023  润新知