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日志并进行多维度分析。
目录
相关文章
|
19天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
156 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
17天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
63 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
6天前
|
缓存 API 数据库
Python哪个框架合适开发速卖通商品详情api?
在跨境电商平台速卖通的商品详情数据获取与整合中,Python 语言及其多种框架(如 Flask、Django、Tornado 和 FastAPI)提供了高效解决方案。Flask 简洁灵活,适合快速开发;Django 功能全面,适用于大型项目;Tornado 性能卓越,擅长处理高并发;FastAPI 结合类型提示和异步编程,开发体验优秀。选择合适的框架需综合考虑项目规模、性能要求和团队技术栈。
18 2
|
19天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP是一种流行的服务器端脚本语言,自诞生以来在Web开发领域占据重要地位。从简单的网页脚本到支持面向对象编程的现代语言,PHP经历了多次重大更新。本文探讨PHP的现代演进历程,重点介绍其在Web开发中的应用及框架创新,如Laravel、Symfony等。这些框架不仅简化了开发流程,还提高了开发效率和安全性。
24 3
|
18天前
|
前端开发 JavaScript 开发工具
从框架到现代Web开发实践
从框架到现代Web开发实践
27 1
|
21天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP 自发布以来一直在 Web 开发领域占据重要地位,历经多次重大更新,从简单的脚本语言进化为支持面向对象编程的现代语言。本文探讨 PHP 的演进历程,重点介绍其在 Web 开发中的应用及框架创新。自 PHP 5.3 引入命名空间后,PHP 迈向了面向对象编程时代;PHP 7 通过优化内核大幅提升性能;PHP 8 更是带来了属性、刚性类型等新特性。
25 3
|
8天前
|
安全 API 数据库
Python哪个框架合适开发淘宝商品详情api?
在数字化商业时代,开发淘宝商品详情API成为企业拓展业务的重要手段。Python凭借其强大的框架支持,如Flask、Django、Tornado和FastAPI,为API开发提供了多样化的选择。本文探讨了这些框架的特点、优势及应用场景,帮助开发者根据项目需求选择最合适的工具,确保API的高效、稳定与可扩展性。
17 0
|
15天前
|
安全 API 网络架构
Python中哪个框架最适合做API?
本文介绍了Python生态系统中几个流行的API框架,包括Flask、FastAPI、Django Rest Framework(DRF)、Falcon和Tornado。每个框架都有其独特的优势和适用场景。Flask轻量灵活,适合小型项目;FastAPI高性能且自动生成文档,适合需要高吞吐量的API;DRF功能强大,适合复杂应用;Falcon高性能低延迟,适合快速API开发;Tornado异步非阻塞,适合高并发场景。文章通过示例代码和优缺点分析,帮助开发者根据项目需求选择合适的框架。
42 0
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
244 3
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1643 14
下一篇
无影云桌面