Python mini-web框架5:路由添加正则和log日志功能

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Python mini-web框架5:路由添加正则和log日志功能

一、给路由添加正则表达式



  • 给路由参数添加正则表达式的原因:在实际开发时,url中往往会带有很多的参数,例如:/add/0003.html 中0003 就是参数,如果没有正则的话,那么就需要编写 N@route 来进行添加 url 对应的函数到字典中,此时字典中的键值对有 N 个,浪费空间,而采用了正则的话,那么只要编写1@route 就可以完成多个 url 例如/add/0008.html/add/0003.html 等对同一个函数,此时的字典中键值对减少很多,如下示例代码


import re
from pymysql import connect
# 定义一个空子典
URL_FUNC_DICT = dict()
def route(url):
        """
        带参数的装饰器来做路由
        :param url: 请求的url
        :return: 返回一个装饰器
        """
        def set_func(func):
            # 往空子典里面添加元素
            URL_FUNC_DICT[url] = func
            def call_func(*args, **kwargs):
                     return func(*args, **kwargs)
            return call_func
        return set_func
@route(r"/add/(\d+)\.html")
def add_focus(ret):
       # 1.获取股票代码
       stock_code = ret.group(1)
       # 2.判断下是否有这个股票代码
       # 创建Connection连接
       conn = connect(host='域名或者公网IP', port=3306, database='数据库名', user='用户名', password='密码',
             charset='utf8')
       # 获得Cursor对象
       cursor = conn.cursor()
       sql = """select * from info where code=%s;"""
       cursor.execute(sql,(stock_code,))
       print("************-----------1------------------")
       # 如果要是没有这个股票代码,那么就认为是非法的请求
       if not cursor.fetchone():
            cursor.close()
            conn.close()
            return "没有这支股票,大哥 ,我们是创业公司,请手下留情..."
       print("************-----------2------------------")
       # 3.在股票存在的情况下查看股票是否关注过
       sql = """select * from focus as f inner join info as i on f.info_id = i.id where i.code=%s;"""
       cursor.execute(sql,(stock_code,))
       # 如果查出来表示关注过
       if cursor.fetchone():
             cursor.close()
             conn.close()
             return "已经关注过了,请勿重复关注..."
       print("************-----------3------------------")
      # 4.在没有关注的情况下,进行关注,也就是往关注的信息表里面添加数据
      sql = """insert into focus (info_id) select id from info where code = %s;"""
      cursor.execute(sql,(stock_code,))
      conn.commit()
      cursor.close()
      conn.close()
      return "关注成功"
def application(evn, start_reponse):
        start_reponse('200 OK', [('Content-Type', 'text/html;charset=utf-8')])
        file_name = evn['PATH_INFO']
        try:
            for url,func in URL_FUNC_DICT.items():
                   ret = re.match(url,file_name)
                   if ret:
                         return func(ret)
                   else:
                         return "请求的url(%s)没有对应的函数...." % file_name
        except Exception as ret:
             return "产生了异常:%s"% str(ret)


二、url 编码



  • 2.1、python3对url编解码
    导入库 urllib.parse


import urllib.parse
  • Python3 url编码


print(urllib.parse.quote("不忘初心,方得始终!"))
打印结果:%E4%B8%8D%E5%BF%98%E5%88%9D%E5%BF%83%EF%BC%8C%E6%96%B9%E5%BE%97%E5%A7%8B%E7%BB%88%EF%BC%81
  • Python3 url解码


print(urllib.parse.unquote('%E4%B8%8D%E5%BF%98%E5%88%9D%E5%BF%83%EF%BC%8C%E6%96%B9%E5%BE%97%E5%A7%8B%E7%BB%88%EF%BC%81'))
打印结果是:不忘初心,方得始终!
  • 完整的代码如下:


import urllib.parse
text = urllib.parse.quote("不忘初心,方得始终!")
print("url编码后的文字=%s"%text)
text = urllib.parse.unquote(text)
print("url解码后的文字=%s"%text)
  • 2.2、浏览器往服务器传内容的时候会对内容进行编码,如果我们的框架在接收到消息后不进行解码直接写入数据库,我们服务器里面存的是url编码的内容,所以我们需要对内容进行解码,再存到数据库,这样下次读取出来的时候不再是url编码的内容


三、logging日志模块



  • 3.1、开发过程中出现bug是必不可免的,你会怎样debug?从第1行代码开始看么?还是有个文件里面记录着哪里错了更方便呢!!!log日志,Python中有个logging模块可以完成相关信息的记录,在debug时用它往往事半功倍
  • 3.2、日志级别:日志一共分成5个等级,从 低到高 分别是:


DEBUG      # 调试模式
INFO       # 确认一切按预期运行
WARNING    # 警告
ERROR      # 错误
CRITICAL   # critical 英[ˈkrɪtɪkl]  严重的;


  • 解释:
  • DEBUG:详细的信息,通常只出现在诊断问题上
  • INFO:确认一切按预期运行
  • WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作。
  • ERROR:更严重的问题,软件没能执行一些功能
  • CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行
  • 总结:这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。默认的是WARNING,当在WARNING或之上时才被跟踪。


  • 3.3、日志输出有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。


  • (1)、将日志输出到控制台,比如,logTest.py 如下:


import logging
logging.basicConfig(level=logging.DEBUG,
                format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
# 开始使用log功能
logging.debug('这是 loggging debug message')
logging.info('这是 loggging info message')
logging.warning('这是 loggging a warning message')
logging.error("这是logging error message")
logging.critical("这是logging critical message")
  • 打印结果如下:


2019-01-17 10:00:53,331 - logTest.py[line:21] - DEBUG: 这是 loggging debug message
2019-01-17 10:00:53,331 - logTest.py[line:22] - INFO: 这是 loggging info message
2019-01-17 10:00:53,331 - logTest.py[line:23] - WARNING: 这是 loggging a warning message
2019-01-17 10:00:53,331 - logTest.py[line:24] - ERROR: 这是logging error message
2019-01-17 10:00:53,331 - logTest.py[line:25] - CRITICAL: 这是logging critical message
  • (2)、将日志输出到文件log.txt,比如,logTest2.py 如下:


import logging
"""
   level:日志等级,5个等级,从小到大依次是:debug、info、warning、error、critical
   filename:要写入的日志文件名字
   filemode:日志写入的模式,a是追加日志信息 w是删除后添加新的日志信息
   format:格式,asctime 时间、filename 报错文件名、lineno 行数 、levelname 报错的等级、message 报错的信息
"""
logging.basicConfig(level=logging.DEBUG,
           filename='./log.txt',
           filemode='a',
           format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
# 开始使用log功能
logging.debug('这是 loggging debug message')
logging.info('这是 loggging info message')
logging.warning('这是 loggging a warning message')
logging.error("这是logging error message")
logging.critical("这是logging critical message")


  • 运行后会生成一个 log.txt 文件


image.png

  • (3)、既要把日志输出到控制台, 还要写入日志文件


这就需要一个叫作 Logger 的对象来帮忙,下面将对他进行详细介绍,现在这里先学习怎么实现把日志既要输出到控制台又要输出到文件的功能。


import logging  
# 第一步,创建一个logger  
logger = logging.getLogger()  
logger.setLevel(logging.DEBUG)  # Log等级总开关  
# 第二步,创建一个handler,用于写入日志文件  
logfile = './log.txt'  
fh = logging.FileHandler(logfile, mode='a')  # open的打开模式这里可以进行参考
fh.setLevel(logging.INFO)  # 输出到file的log等级的开关  
# 第三步,再创建一个handler,用于输出到控制台  
ch = logging.StreamHandler()  
ch.setLevel(logging.WARNING)   # 输出到console的log等级的开关  
# 第四步,定义handler的输出格式  
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")  
fh.setFormatter(formatter)  
ch.setFormatter(formatter)  
# 第五步,将logger添加到handler里面  
logger.addHandler(fh)  
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')
  • 运行时终端的输出结果:


2019-01-17 11:21:01,785 - logTest3.py[line:28] - WARNING: 这是 logger warning message
2019-01-17 11:21:01,785 - logTest3.py[line:29] - ERROR: 这是 logger error message
2019-01-17 11:21:01,785 - logTest3.py[line:30] - CRITICAL: 这是 logger critical message
  • log.txt 中,有如下数据:


2019-01-17 11:21:01,784 - logTest3.py[line:27] - INFO: 这是 logger info message
2019-01-17 11:21:01,785 - logTest3.py[line:28] - WARNING: 这是 logger warning message
2019-01-17 11:21:01,785 - logTest3.py[line:29] - ERROR: 这是 logger error message
2019-01-17 11:21:01,785 - logTest3.py[line:30] - CRITICAL: 这是 logger critical message
  • 3.4、日志格式说明
  • logging.basicConfig函数中,可以指定日志的输出格式format,这个参数可以输出很多有用的信息,如下:


%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
  • 在工作中给的常用格式如下:


format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'


  • 这个格式可以输出日志的打印时间,是哪个模块输出的,输出的日志级别是什么,以及输入的日志内容。
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7天前
|
SQL 存储 JSON
更快更强,SLS 推出高性能 SPL 日志查询模式
从海量的日志数据中,按照各种灵活的条件进行即时查询搜索,是可观测场景下的基本需求。本文介绍了 SLS 新推出的高性能 SPL 日志查询模式,支持 Unix 风格级联管道式语法,以及各种丰富的 SQL 处理函数。同时通过计算下推、向量化计算等优化,使得 SPL 查询可以在数秒内处理亿级数据,并支持 SPL 过滤结果分布图、随机翻页等特性。
256 65
|
5天前
|
数据采集 监控 数据安全/隐私保护
掌握Selenium爬虫的日志管理:调整–log-level选项的用法
在Selenium Web数据采集时,日志管理至关重要。通过调整`–log-level`参数可优化日志详细度,如设置为`INFO`记录一般操作信息。结合代理IP、Cookie及user-agent配置,不仅能提高采集成功率,还能规避反爬机制。合理选择日志级别有助于调试与性能平衡,在复杂的数据采集任务中保持程序稳定与可控。
掌握Selenium爬虫的日志管理:调整–log-level选项的用法
|
4天前
|
XML Java Maven
Spring5入门到实战------16、Spring5新功能 --整合日志框架(Log4j2)
这篇文章是Spring5框架的入门到实战教程,介绍了Spring5的新功能——整合日志框架Log4j2,包括Spring5对日志框架的通用封装、如何在项目中引入Log4j2、编写Log4j2的XML配置文件,并通过测试类展示了如何使用Log4j2进行日志记录。
Spring5入门到实战------16、Spring5新功能 --整合日志框架(Log4j2)
|
6天前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
10天前
|
存储 缓存 监控
【嵌入式SD NAND】基于FATFS/Littlefs文件系统的日志框架实现
综上所述,构建一个基于FATFS/Littlefs文件系统的日志框架需要对文件系统的操作有深入理解,并以此为基础设计一套完整的日志处理机制。这样的框架不仅能够确保日志数据的完整性和系统的鲁棒性,同时还能够满足嵌入式系统对于性能和资源使用的严格要求。
32 4
|
8天前
|
Java 应用服务中间件
SpringBoot 记录 access.log 日志
SpringBoot 记录 access.log 日志
19 0
SpringBoot 记录 access.log 日志
|
19天前
|
SQL 存储 监控
(十一)MySQL日志篇之undo-log、redo-log、bin-log.....傻傻分不清!
任何项目都会有日志,MySQL也不例外,而且MySQL更是其中的佼佼者,日志种类繁多,而本篇的目的就是全解MySQL中的各类日志,如撤销日志、错误日志、慢查询日志、中继日志、回滚日志.....
|
1天前
|
消息中间件 监控 Kafka
实时计算 Flink版产品使用问题之怎么调整Flink Web U显示的日志行数
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
5天前
|
开发框架 .NET API
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
|
5天前
|
存储 Kubernetes Java
阿里泛日志设计与实践问题之在写多查少的降本场景下,通过SLS Scan方案降低成本,如何实现
阿里泛日志设计与实践问题之在写多查少的降本场景下,通过SLS Scan方案降低成本,如何实现