Flask 备注一(单元测试,Debugger, Logger)

Flask 备注一(单元测试,Debugger, Logger)

Flask是一个使用python开发Web程序的框架。依赖于Werkzeug提供完整的WSGI支持,以及Jinja2提供templates支持。Flask的设计理念是提供Micro以及方便的框架。"Micro"是因为除了提供基本特性功能的实现外,其他的功能(例如数据库访问)都是通过extension来完成。方便的特点是因为提供了简单易用的必要特性和功能,提供的功能包含:

  1. 内置的开发服务器和调试工具。
  2. 集成单元测试支持。
  3. 支持Templates(依赖JinJa2提供)
  4. 完整的WSGI支持(依赖Werkzeug提供)
  5. 安全Cookie和Sessions
  6. Thread-Locals,例如在每个Request里面的对象只在线程里面有意义。

Templates

Flask使用jinja2作为templates引擎。jinjia2的默认的语法设定如下:

  • {%. .. %} 包含statements(逻辑处理代码块)
  • {{ ... }} 包含expressions (输出到tempalte的语句)
  • {# ... #} 包含comments (注释,不会输出到template的语句)
  • # ... ## 包含单行statements (单行处理代码块)

单元测试

Flask通过test_client提供了非常简单的方式来创建测试的上下文环境(Local Context)。这样可以通过各种方式来完成单元测试,最基本的方式是通过python自带的unittest来完成集成的测试用例。

unittest

使用unittest的Flask单元测试的框架如下:

import os
import xxxx
import unittest
import tempfile

class XxxxTestCase(unittest.TestCase):

    def setUp(self):
        self.db_fd, xxxx.app.config[‘DATABASE‘] = tempfile.mkstemp()
        xxxx.app.config[‘TESTING‘] = True
        self.app = xxxx.app.test_client()
        xxxx.init_db()

    def tearDown(self):
        os.close(self.db_fd)
        os.unlink(xxxx.app.config[‘DATABASE‘])

if __name__ == ‘__main__‘:
    unittest.main()

在上述例子里面:

  1. xxxx是一个自定义的简单的flask程序,xxxx.app是一个Flask类的对象,对应一个Web应用。
  2. 在setUp函数里面,将Flask的Web应用的TESTING参数配置为True,并创建了一个对应的测试客户端(test_client),包含测试需要的上下文环境。
  3. 在setUp函数里面,创建了xxxx的数据库文件并进行了初始化。
  4. 在tearDown函数里面,关闭了数据库文件并删除。
    在unittest中测试用例的函数必须哟以test单词开始,例如testFunc1,这样测试框架可以将此函数作为测试用例执行。执行测试用例之前先执行setUp函数进行初始化,之后执行tearDown进行资源释放。基本的测试用例如下:

    def testemptydb(self):
    rv = self.app.get(‘/‘)
    assert ‘No entries here so far‘ in rv.data

Local Context

unittest框架通过setUp创建了testclient以及需要的上下文环境,并且在tearDown函数里面进行销毁。同样可以使用testclient在任意代码中完成验证测试。因为test_client创建了一个临时的上下文环境,在任何区域中都可以通过with语句是此context在范围内有效,因此在这个范围内可以验证request以及session的信息。
验证request信息的简单例子:

with app.test_client() as c:
    rv = c.get(‘/?number=42‘)
    assert request.args[‘number‘] == ‘42‘

验证session信息的简单例子:

with app.test_client() as c:
    rv = c.get(‘/‘)
    assert flask.session[‘foo‘] == 42

如果需要修改testclient创建的临时context中的session信息,可以通过sessiontranscation来获取session对象进行修改。如下简单实例:

with app.test_client() as c:
    with c.session_transcation() as sess:
        sess[‘a_key‘] = ‘a value‘

Debug&Logging

在程序中,错误永远无法避免,错误有可能是代码逻辑问题,服务器问题,网络问题或者是硬件问题,环境问题等等。Flask提供了两种方式定位问题,其一可以打开程序的调试模式,通过调试器(debugger)跟踪程序的执行信息;另外就是Flask提供了完善的日志系统,记录程序的运行信息。

Debug

Flask通过必要的参数设置,来确定是否使用Debug模式以及是否使用自带的调试器。这些参数包含:

  • debug。True: 设置Debug模式; False: 非Debug模式
  • use_debugger。True: 使用内部调试器; Flase: 不实用内部调试器
  • use_reloader。True: 在Excpetion时,是否reload和fork当前进程进行调试; False: Nothing.

如果使用第三方类似于Aptana/Eclipse等调试器,需要设置debug为True,usedebugger和usereloader为False。

通过内置的debugger,当程序出现exception时,在错误界面提供一个交互式的界面,而且在这个界面里面可以执行任意的代码进行程序调试。这样存在着巨大的安全隐患,因此永远不要在产品服务器上开启调试模式

Logging

Flask附带的Logger依赖于Python内置的日志系统,通过默认Logging库设置日志的处理Handler,日志Format以及处理的Level。程序中通过Flask的Logger所写的Log通过系统自带的日志系统进行过滤和格式化,然后输出到所设置的Handler中。

handler可以是文件也可以是邮件,一般情况下的应用场景是,将大部分的日志信息保存到文件中,将重点需要关注的日志信息发送到邮件中。

  • 文件Handler。文件Handler包含四种:

    • FileHandler,对应文件系统的一个文件。
    • RotatingFileHandler, 对应文件系统的一个文件,在输出一定数量的信息之后,重头开始。
    • NTEventLogHandler,对应Windows操作系统的日志系统。
    • SysLogHandler,对应Unix Syslog系统。
  • 邮件Handler。通常使用smtphandler进行邮件发送。
  • Handler的简单示例如下:

    if not app.debug:
    import logging
    from logging.handler import SMTPHandler, FileHandler

    file_handler = FileHandler(/var/test/flask.log)
    file_handler.setLevel(logging.WARNING)
    
    email_handler = SMTPHandler(‘127.0.0.1‘,
                                ‘[email protected]‘
                                ADMINS,
                                ‘Your Application Failed!!!‘)
    app.logger.addHandler(file_handler)
    app.logger.addHandler(email_handler)
    

Formatter是Python自带的日志系统提供的,可以对Handler进行设置需要保存的信息格式。一般情况下,在邮件Handler中保存详细的多行文本信息;在文件Handler里面保存单行重要信息。Log的格式参数如下:

  • %(levelname)s || 日志级别(包含:‘DEBUG‘, ‘INFO‘, ‘WARNING‘, ‘ERROR‘, ‘CRITICAL‘) ||
  • %(pathname)s || Log产生的源文件路径 ||
  • %(filename)s || Log产生的源文件名称 ||
  • %(module)s || Log产生的模块 ||
  • %(funcName)s || Log产生的函数名称 ||
  • %(lineno)d || Log产生的所在文件行号 ||
  • %(asctime)s || Log产生的时间格式是:YYYY-MM-DD hh-mm-ss, mmm(,之后是毫秒数)
  • %(message)s || Log的信息 ||

Email日志格式设置的简单示例:

from logging import Formatter
mail_handler.setFormatter(Formatter(‘‘‘
    Message type:       %(levelname)s
    Location:           %(pathname)s:%(lineno)d
    Module:             %(module)s
    Function:           %(funcName)s
    Time:               %(asctime)s
    Message:            %(message)s
‘‘‘))

文件日志格式设置的简单示例:

from logging import Formatter
file_handler.setFormatter(Formatter(
    ‘%(asctime)s %(levelname)s: %(message)s ‘
    ‘[in %(pathname)s:%(lineno)d]‘
    ))

Flask中使用的第三库都有自己的日志策略,同样可以使用getlogger获取每个依赖库的logger设置统一的Handler。如下示例:

from logging import getLogger
loggers = [app.logger, getLogger(‘sqlalchemy‘),
           getLogger(‘otherlibrary‘)]
for logger in loggers:
    logger.addHandler(mail_handler)
    logger.addHandler(file_handler)
时间: 2024-08-02 06:52:34

Flask 备注一(单元测试,Debugger, Logger)的相关文章

Flask备注二(Configurations, Signals)

Flask备注二(Configuration, Signals) Flask是一个使用python开发Web程序的框架.依赖于Werkzeug提供完整的WSGI支持,以及Jinja2提供templates支持.Flask的设计理念是提供Micro以及方便的框架."Micro"是因为除了提供基本特性功能的实现外,其他的功能(例如数据库访问)都是通过extension来完成.方便的特点是因为提供了简单易用的必要特性和功能,提供的功能包含: 内置的开发服务器和调试工具. 集成单元测试支持.

Flask备注4(Structure)

Flask备注4(Structure) package 通过Flask可以非常简单的通过一个module(一个py文件)创建一个简单的application.这种简单程序的文件结构如下: /yourapplication /yourapplication.py /static /style.css /templates layout.html index.html login.html ... 这种结构对于较大或者复杂的程序并不合适.对于复杂程序可以通过python自带的package结构来组织

【简说Python WEB】Flask应用的单元测试

[简说Python WEB]Flask应用的单元测试 tests/test_basics.py import unittest from flask import current_app from app import create_app, db class BasicsTestCase(unittest.TestCase): def setUp(self): self.app = create_app('testing') self.app_context = self.app.app_co

【Flask Rest API 单元测试】

Flask简单的Rest API 接口测试示例代码: import unittest import json from app import app class BasicTestCase(unittest.TestCase): def setUp(self): self.client = app.test_client() self.client.testing = True def tearDown(self): """""" pass de

Flask —— 使用Python和OpenShift进行即时Web开发

最近Packtpub找到了我,让我给他们新出版的关于Flask的书写书评.Flask是一个很流行的Python框架.那本书是Ron DuPlain写的<Flask 即时Web开发>.我决定把“30天学习30种新技术”挑战的第三天花在Flask上.在本文中,我首先将介绍Flask框架的一些基本知识,然后提供一个短篇的书评.同样,我也会把示例应用移植到OpenShift上.对于Flask而言我不是一个完全意义上的新手,我也用它创建过示例应用.对我来说,这是一次很好的温习. 给不了解这一系列文章的读

第七章:错误处理

感谢作者 –> 原文链接 本文翻译自The Flask Mega-Tutorial Part VII: Error Handling 这是Flask Mega-Tutorial系列的第七部分,我将告诉你如何在Flask应用中进行错误处理. 本章将暂停为microblog应用开发新功能,转而讨论处理BUG的策略,因为它们总是无处不在.为了帮助本章的演示,我故意在第六章新增的代码中遗留了一处BUG. 在继续阅读之前,看看你能不能找到它! 本章的GitHub链接为:Browse, Zip, Diff.

一个简单好用的日志框架NLog

之前我介绍过如何使用log4net来记录日志,但最近喜欢上了另一个简单好用的日志框架NLog. 关于NLog和log4net的比较这里就不多讨论了,感兴趣的朋友可以参看.NET日志工具介绍和log4net vs. Nlog这两篇文章.本文主要介绍一下如何在项目中使用NLog. 在Nuget中安装NLog NLog可以直接使用Nuget安装: PM > Install-Package Nlog 使用NLog NLog的使用方式基本上和其它的Log库差不多,分为Trace.Debug.Info.Er

拥抱.NET Core系列:Logging (1)

在之前我们简单介绍了 .NET Core 中的 DI组件,没来及了解的童鞋可以翻翻我之前的文章. 接下来会对 .NET Core 中的 Logging 进行介绍. 本文中使用了"Microsoft.Extensions.Logging.Console"做为输出目标,后续文章会详解. Logging 中的三剑客 可以看到 Logging 的核心抽象就是三个接口,分别是: ILogger:负责具体的日志写入逻辑,如:FileLogger,ConsoleLogger,SQLLogger,El

Android剖析和运行机制

翻译之<Android Anatomy and Physiology>,下载地址:http://download.csdn.net/detail/wuxiaoer717/6839427 大纲: 1. Android剖析 Linux内核 本地库(Native Libraries) Android运行时(Android Runtime) 应用框架 2. Android运行机制 启动流程 层间交互(Layer Interaction) 一. Android剖析 如下图所示为Android的架构图 1