我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Flask测试和部署

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Flask测试和部署

一 蓝图Blueprint

为什么学习蓝图?

我们学习Flask框架,是从写单个文件,执行hello world开始的。我们在这单个文件中可以定义路由、视图函数、定义模型等等。但这显然存在一个问题:随着业务代码的增加,将所有代码都放在单个程序文件中,是非常不合适的。这不仅会让代码阅读变得困难,而且会给后期维护带来麻烦。

如下示例:我们在一个文件中写入多个路由,这会使代码维护变得困难。

 from flask import Flask    
    app = Flask(__name__)    
    @app.route('/')
    def index():
        return 'index'

    @app.route('/list')
    def list():
        return 'list'

    @app.route('/detail')
    def detail():
        return 'detail'
View Code

 

问题:一个程序执行文件中,功能代码过多。就是让代码模块化。根据具体不同功能模块的实现,划分成不同的分类,降低各功能模块之间的耦合度。python中的模块制作和导入就是基于实现功能模块的封装的需求。

尝试用模块导入的方式解决: 我们把上述一个py文件的多个路由视图函数给拆成两个文件:app.py和admin.py文件。app.py文件作为程序启动文件,因为admin文件没有应用程序实例app,在admin文件中要使用app.route路由装饰器,需要把app.py文件的app导入到admin.py文件中。

# 文件app.py
from flask import Flask
# 导入admin中的内容
from admin import *
app = Flask(__name__)

@app.route('/')
def index():
    return 'index'

if __name__ == '__main__':
    app.run()


# 文件admin.py    
from app import app


@app.route('/list')
def list():
    return 'list'

@app.route('/detail')
def detail():
    return 'detail'
View Code

启动app.py文件后,发访问http://127.0.0.1:5000/list,此时会报错:ImportError: cannot import name 'app'。因为模块间产生了死锁。

 

什么是蓝图?

蓝图:用于实现单个应用的视图、模板、静态文件的集合。

蓝图就是模块化处理的类。

简单来说,蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能。 在Flask中,使用蓝图可以帮助我们实现模块化应用的功能。

 

蓝图的运行机制:

蓝图是保存了一组将来可以在应用对象上执行的操作。注册路由就是一种操作,当在程序实例上调用route装饰器注册路由时,这个操作将修改对象的url_map路由映射列表。当我们在蓝图对象上调用route装饰器注册路由时,它只是在内部的一个延迟操作记录列表defered_functions中添加了一个项。当执行应用对象的 register_blueprint() 方法时,应用对象从蓝图对象的 defered_functions 列表中取出每一项,即调用应用对象的 add_url_rule() 方法,这将会修改程序实例的路由映射列表。

 

蓝图的使用:

1.创建蓝图对象。

#Blueprint必须指定两个参数,admin表示蓝图的名称,__name__表示蓝图所在模块
admin = Blueprint('admin',__name__)

2.注册蓝图路由。

@admin.route('/admin')
def admin_index():
    return 'admin_index'

3.在程序实例中注册该蓝图。

app.register_blueprint(admin,url_prefix='/admin')

示例, 创建myapp.py 和 蓝图:good.py文件

myapp.py:

from flask import Blueprint


get_list = Blueprint("get_list", __name__)


@get_list.route('/get_list')
def goods_list():
    return 'goods_list'
View Code

good.py:

from flask import Flask
from good import get_list

app = Flask(__name__)

app.register_blueprint(get_list)


@app.route('/index')
def index():
    return 'index'


if __name__ == '__main__':
    app.run()
View Code

查看路由:

 

二 单元测试

为什么要测试?

Web程序开发过程一般包括以下几个阶段:[需求分析,设计阶段,实现阶段,测试阶段]。其中测试阶段通过人工或自动来运行测试某个系统的功能。目的是检验其是否满足需求,并得出特定的结果,以达到弄清楚预期结果和实际结果之间的差别的最终目的。

测试的分类:

测试从软件开发过程可以分为:单元测试、集成测试、系统测试等。在众多的测试中,与程序开发人员最密切的就是单元测试,因为单元测试是由开发人员进行的,而其他测试都由专业的测试人员来完成。所以我们主要学习单元测试。

 

什么是单元测试?

程序开发过程中,写代码是为了实现需求。当我们的代码通过了编译,只是说明它的语法正确,功能能否实现则不能保证。 因此,当我们的某些功能代码完成后,为了检验其是否满足程序的需求。可以通过编写测试代码,模拟程序运行的过程,检验功能代码是否符合预期。

单元测试就是开发者编写一小段代码,检验目标代码的功能是否符合预期。通常情况下,单元测试主要面向一些功能单一的模块进行。

举个例子:一部手机有许多零部件组成,在正式组装一部手机前,手机内部的各个零部件,CPU、内存、电池、摄像头等,都要进行测试,这就是单元测试。

在Web开发过程中,单元测试实际上就是一些“断言”(assert)代码。

断言就是判断一个函数或对象的一个方法所产生的结果是否符合你期望的那个结果。 python中assert断言是声明布尔值为真的判定,如果表达式为假会发生异常。单元测试中,一般使用assert来断言结果。

断言方法的使用:

断言语句类似于:

if not expression:
    raise AssertionError

常用的断言方法:

assertEqual     如果两个值相等,则pass
assertNotEqual  如果两个值不相等,则pass
assertTrue      判断bool值为True,则pass
assertFalse     判断bool值为False,则pass
assertIsNone    不存在,则pass
assertIsNotNone 存在,则pass

 

如何测试?

简单的测试用例:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,

def fibo(x):
    if x == 0:
        resp = 0
    elif x == 1:
        resp = 1
    else:
        return fibo(x-1) + fibo(x-2)
    return resp
assert fibo(5) == 5
View Code

 

单元测试的基本写法:

 首先,定义一个类,继承自unittest.TestCase

import unittest
class TestClass(unitest.TestCase):
    pass

其次,在测试类中,定义两个测试方法

import unittest
class TestClass(unittest.TestCase):

    #该方法会首先执行,方法名为固定写法
    def setUp(self):
        pass

    #该方法会在测试代码执行完后执行,方法名为固定写法
    def tearDown(self):
        pass

最后,在测试类中,编写测试代码

import unittest
class TestClass(unittest.TestCase):

    #该方法会首先执行,相当于做测试前的准备工作
    def setUp(self):
        pass

    #该方法会在测试代码执行完后执行,相当于做测试后的扫尾工作
    def tearDown(self):
        pass
    #测试代码
    def test_app_exists(self):
        pass

 

登录测试:

 login.py:

# coding:utf-8

from flask import Flask, request, jsonify


app = Flask(__name__)


@app.route("/login", methods=["POST"])
def login():
    """登录"""
    name = request.form.get("name")
    password = request.form.get("password")

    # ""  0  [] () {} None 在逻辑判断时都是假
    if not all([name, password]):
        # 表示name或password中有一个为空或者都为空
        return jsonify(code=1, message="参数不完整")

    if name == "admin" and password =="123456":
        return jsonify(code=0, message="OK")
    else:
        return jsonify(code=2, message="用户名或密码错误")


if __name__ == '__main__':
    app.run()
View Code

test_login.py :

# coding:utf-8

import unittest
from login import app
import json


class TestLogin(unittest.TestCase):
    """定义测试案例"""
    def setUp(self):
        """在执行具体的测试方法前,先被调用"""
        # 可以使用python的http标准客户端进行测试
        # urllib  urllib2  requests

        # 使用flask提供的测试客户端进行测试
        self.client = app.test_client()

    def test_empty_name_password(self):
        """测试模拟场景,用户名或密码不完整"""
        # 使用客户端向后端发送post请求, data指明发送的数据,会返回一个响应对象
        response = self.client.post("/login", data={})

        # respoonse.data是响应体数据
        resp_json = response.data

        # 按照json解析
        resp_dict = json.loads(resp_json)

        # 使用断言进行验证
        self.assertIn("code", resp_dict)

        code = resp_dict.get("code")
        self.assertEqual(code, 1)

        # 测试只传name
        response = self.client.post("/login", data={"name": "admin"})

        # respoonse.data是响应体数据
        resp_json = response.data

        # 按照json解析
        resp_dict = json.loads(resp_json)

        # 使用断言进行验证
        self.assertIn("code", resp_dict)

        code = resp_dict.get("code")
        self.assertEqual(code, 1)

    def test_wrong_name_password(self):
        """测试用户名或密码错误"""
        # 使用客户端向后端发送post请求, data指明发送的数据,会返回一个响应对象
        response = self.client.post("/login", data={"name": "admin", "password": "123"})

        # respoonse.data是响应体数据
        resp_json = response.data

        # 按照json解析
        resp_dict = json.loads(resp_json)

        # 使用断言进行验证
        self.assertIn("code", resp_dict)

        code = resp_dict.get("code")
        self.assertEqual(code, 2)


if __name__ == '__main__':
    unittest.main()
View Code

 

数据库测试:

#coding=utf-8
import unittest
from author_book import *

#自定义测试类,setUp方法和tearDown方法会分别在测试前后执行。以test_开头的函数就是具体的测试代码。

class DatabaseTest(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@localhost/test0'
        self.app = app
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

    #测试代码
    def test_append_data(self):
        au = Author(name='test')
        bk = Book(info='python')
        db.session.add_all([au,bk])
        db.session.commit()
        author = Author.query.filter_by(name='test').first()
        book = Book.query.filter_by(info='python').first()
        #断言数据存在
        self.assertIsNotNone(author)
        self.assertIsNotNone(book)
View Code

 

三 部署

当我们执行下面的hello.py时,使用的flask自带的服务器,完成了web服务的启动。在生产环境中,flask自带的服务器,无法满足性能要求,我们这里采用Gunicorn做wsgi容器,来部署flask程序。Gunicorn(绿色独角兽)是一个Python WSGI的HTTP服务器。从Ruby的独角兽(Unicorn )项目移植。该Gunicorn服务器与各种Web框架兼容,实现非常简单,轻量级的资源消耗。Gunicorn直接用命令启动,不需要编写配置文件,相对uWSGI要容易很多。

区分几个概念:

WSGI:全称是Web Server Gateway Interface(web服务器网关接口),它是一种规范,它是web服务器和web应用程序之间的接口。它的作用就像是桥梁,连接在web服务器和web应用框架之间。

uwsgi:是一种传输协议,用于定义传输信息的类型。

uWSGI:是实现了uwsgi协议WSGI的web服务器。

我们的部署方式: nginx + gunicorn + flask

# hello.py

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return '<h1>hello world</h1>'

if __name__ == '__main__':
    app.run(debug=True)
View Code

使用Gunicorn:

web开发中,部署方式大致类似。简单来说,前端代理使用Nginx主要是为了实现分流、转发、负载均衡,以及分担服务器的压力。Nginx部署简单,内存消耗少,成本低。Nginx既可以做正向代理,也可以做反向代理。

正向代理:请求经过代理服务器从局域网发出,然后到达互联网上的服务器。

特点:服务端并不知道真正的客户端是谁。

反向代理:请求从互联网发出,先进入代理服务器,再转发给局域网内的服务器。

特点:客户端并不知道真正的服务端是谁。

区别:正向代理的对象是客户端。反向代理的对象是服务端。

安装gunicorn

pip install gunicorn

直接运行:

#直接运行,默认启动的127.0.0.1::8000
gunicorn 运行文件名称:Flask程序实例名

指定进程和端口号: -w: 表示进程(worker)。 -b:表示绑定ip地址和端口号(bind)

$gunicorn -w 4 -b 127.0.0.1:5001 运行文件名称:Flask程序实例名                 # 加 -d 守护进程

 

Nginx配置:

默认安装到/usr/local/nginx/目录,进入目录。

启动nginx:

#启动
sudo sbin/nginx
#查看
ps aux | grep nginx
#停止
sudo sbin/nginx -s stop

打开/usr/local/nginx/conf/nginx.conf文件

server {
    # 监听80端口
    listen 80;
    # 本机
    server_name localhost; 
    # 默认请求的url
    location / {
        #请求转发到gunicorn服务器
        proxy_pass http://127.0.0.1:5001; 
        #设置请求头,并将头信息传递给服务器端 
        proxy_set_header Host $host; 
    }
}

 

四 Restful

2000年,Roy Thomas Fielding博士在他的博士论文《Architectural Styles and the Design of Network-based Software Architectures》中提出了几种软件应用的架构风格,REST作为其中的一种架构风格在这篇论文中进行了概括性的介绍。

REST:Representational State Transfer的缩写,翻译:“具象状态传输”。一般解释为“表现层状态转换”。

REST是设计风格而不是标准。是指客户端和服务器的交互形式。我们需要关注的重点是如何设计REST风格的网络接口。

  • REST的特点:
  • 具象的。一般指表现层,要表现的对象就是资源。比如,客户端访问服务器,获取的数据就是资源。比如文字、图片、音视频等。

  • 表现:资源的表现形式。txt格式、html格式、json格式、jpg格式等。浏览器通过URL确定资源的位置,但是需要在HTTP请求头中,用Accept和Content-Type字段指定,这两个字段是对资源表现的描述。

  • 状态转换:客户端和服务器交互的过程。在这个过程中,一定会有数据和状态的转化,这种转化叫做状态转换。其中,GET表示获取资源,POST表示新建资源,PUT表示更新资源,DELETE表示删除资源。HTTP协议中最常用的就是这四种操作方式。

    • RESTful架构:
    • 每个URL代表一种资源;
    • 客户端和服务器之间,传递这种资源的某种表现层;
    • 客户端通过四个http动词,对服务器资源进行操作,实现表现层状态转换。

如何设计符合RESTful风格的API:

1.域名:

将api部署在专用域名下:

http://api.example.com

或者将api放在主域名下:

http://www.example.com/api/

2.版本:

将API的版本号放在url中。

http://www.example.com/app/1.0/info
http://www.example.com/app/1.2/info

3.路径:

路径表示API的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。

错误示例:

http://www.example.com/getGoods
http://www.example.com/listOrders

正确示例:

#获取单个商品
http://www.example.com/app/goods/1
#获取所有商品
http://www.example.com/app/goods

4.使用标准的HTTP方法:

对于资源的具体操作类型,由HTTP动词表示。 常用的HTTP动词有四个。

GET     SELECT :从服务器获取资源。
POST    CREATE :在服务器新建资源。
PUT     UPDATE :在服务器更新资源。
DELETE  DELETE :从服务器删除资源。

示例:

#获取指定商品的信息
GET http://www.example.com/goods/ID
#新建商品的信息
POST http://www.example.com/goods
#更新指定商品的信息
PUT http://www.example.com/goods/ID
#删除指定商品的信息
DELETE http://www.example.com/goods/ID

5.过滤信息:

如果资源数据较多,服务器不能将所有数据一次全部返回给客户端。API应该提供参数,过滤返回结果。 实例:

#指定返回数据的数量
http://www.example.com/goods?limit=10
#指定返回数据的开始位置
http://www.example.com/goods?offset=10
#指定第几页,以及每页数据的数量
http://www.example.com/goods?page=2&per_page=20

6.状态码:

服务器向用户返回的状态码和提示信息,常用的有:

200 OK  :服务器成功返回用户请求的数据
201 CREATED :用户新建或修改数据成功。
202 Accepted:表示请求已进入后台排队。
400 INVALID REQUEST :用户发出的请求有错误。
401 Unauthorized :用户没有权限。
403 Forbidden :访问被禁止。
404 NOT FOUND :请求针对的是不存在的记录。
406 Not Acceptable :用户请求的的格式不正确。
500 INTERNAL SERVER ERROR :服务器发生错误。

7.错误信息:

一般来说,服务器返回的错误信息,以键值对的形式返回。

{
    error:'Invalid API KEY'
}

8.响应结果:

针对不同结果,服务器向客户端返回的结果应符合以下规范。

#返回商品列表
GET    http://www.example.com/goods
#返回单个商品
GET    http://www.example.com/goods/cup
#返回新生成的商品
POST   http://www.example.com/goods
#返回一个空文档
DELETE http://www.example.com/goods

9.使用链接关联相关的资源:

在返回响应结果时提供链接其他API的方法,使客户端很方便的获取相关联的信息。

10.其他:

服务器返回的数据格式,应该尽量使用JSON,避免使用XML。

 

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Flask测试和部署

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Flask测试和部署

一 蓝图Blueprint为什么学习蓝图?我们学习Flask框架,是从写单个文件,执行hello world开始的。我们在这单个文件中可以定义路由、视图函数、定义模型等等。但这显然存在一个问题:随着业务代码的增加,将所有代码都放在单个程序文
2023-01-31

gunicorn怎么部署flask

Gunicorn部署Flask应用的步骤如下:1、在终端或命令行中输入“pip install gunicorn”命令来安装Gunicorn;2、创建Flask应用;3、在终端或命令行中输入“flask run”命令来启动Flask应用程序
gunicorn怎么部署flask
2023-12-19

Flask项目怎么部署

本文小编为大家详细介绍“Flask项目怎么部署”,内容详细,步骤清晰,细节处理妥当,希望这篇“Flask项目怎么部署”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。宝塔更新Python版本因为在宝塔中的Python
2023-06-29

CentOS7部署Flask(Apache、mod_wsgi、Python36、venv)

一、安装Apache# yum install -y httpd httpd-devel# systemctl start httpd.service # 启动 # systemctl stop httpd.service #
2022-06-04

Gunicorn和Flask的优化部署:提升部署方案的最佳实践

Gunicorn和Flask的最佳实践:如何优化你的部署方案?引言:Gunicorn是一个高性能的Python WSGI服务器,而Flask是一个轻量级的Python Web框架。二者的结合可以帮助开发者快速构建高效的Web应用。然而,在
Gunicorn和Flask的优化部署:提升部署方案的最佳实践
2024-01-17

Flask + Gunicorn + Nginx的部署方式

本篇内容介绍了“Flask + Gunicorn + Nginx的部署方式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!WSGI容器——Gu
2023-06-04

使用gunicorn部署Flask项目

[*] 本文出处:http://b1u3buf4.xyz/[*] 本文作者:B1u3Buf4[*] 本文授权:禁止转载从自己的博客移动过来。gunicorn是一个python Wsgi的WEB服务框架,只支持在Unix系统上运行,来源于Ru
2023-01-30

使用flask开发api——部署fla

用flask开发了服务端的api,记录部署上服务器的过程,以供后续使用。安装python3.5本身服务器已经安装了python3,并且版本为3.5,这里不重新安装,如果服务器中没有安装python3,则进行安装$ sudo apt-get
2023-01-31

如何利用GitLab进行多环境部署和测试

如何利用GitLab进行多环境部署和测试引言:随着软件开发的迅猛发展,项目中常常会涉及到多个环境的部署和测试。为了简化部署流程和提高交付效率,利用GitLab进行多环境部署和测试成为了一种常见的做法。本文将介绍如何在GitLab中配置和管理
2023-10-25

部署Gunicorn和Flask的无懈可击的组合

Gunicorn和Flask:完美的部署组合,需要具体代码示例概述:对于开发者来说,选择适合的部署方式是非常重要的,尤其是对于Python的Web应用程序而言。在Python的Web框架中,Flask是非常流行的选择,而Gunicorn则
部署Gunicorn和Flask的无懈可击的组合
2024-01-17

Flask应用如何快速部署

Flask应用如何快速部署,需要具体代码示例Flask是一个轻量级的Python Web应用框架,其设计理念简洁明了、灵活可扩展,被越来越多的Python开发者所使用。然而,将Flask应用部署到服务器上,对于新手来说可能有些棘手。本篇
Flask应用如何快速部署
2024-01-19

Flask应用的Gunicorn部署指南

如何使用Gunicorn部署Flask应用?Flask是一个轻量级的Python Web框架,被广泛应用于开发各种类型的Web应用。而Gunicorn(Green Unicorn)是一个基于Python的HTTP服务器,用于运行WSGI(
Flask应用的Gunicorn部署指南
2024-01-17

flask部署到windows云服务器

安装和配置Flask首先,需要在Windows上安装Flask。你可以从官网上下载Flask的安装程序,然后按照安装向导的指引进行操作。一旦安装完成,你需要将其添加到你的环境变量中。Flask有一个路由来管理不同的服务器,因此你需要在Windows上为Flask指定路由。在路由配置中,你可以指定你想要将Flask部署到
flask部署到windows云服务器
2023-10-28

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录