亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

sanic使用記錄

標簽:
Java Python

在使用python异步的时候,我了解到了sanic这个据说是最快的web服务框架,其支持异步请求处理机制,这意味你可以使用python3.5的async/await来编写无阻塞的异步程序。
于是我利用业余时间使用sanic编写了这个项目。
以后这篇文章的更新都直接放在博客了,这里就先不更了:http://blog.howie6879.cn/post/35/

1.前言

在使用过程中,我尽量将程序编写成异步的,首先进行安装:

python -m pip install sanic

sanic的文档写得很详细,但是在使用过程中我还是有些问题。
下面记录的都是我在使用sanic过程中遇到的问题,后续有新问题会继续补充:

  • 1.blueprint

  • 2.html templates编写(引入jinja2)

  • 3.session(引入sanic_session)

  • 4.缓存(引入aiocache)

  • 5.api接口验证(自定义一个装饰器)

  • 6.恶意将其他域名绑定到你的网站独立ip

2.问题记录

2.1.blueprint

借用官方文档的例子,一个简单的sanic服务就搭好了:

# main.pyfrom sanic import Sanicfrom sanic.response import json

app = Sanic()@app.route("/")async def test(request):
    return json({"hello": "world"})#访问http://0.0.0.0:8000/即可if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

上面的例子可以当做一个完整的小应用,关于blueprint的概念,可以这么理解,一个蓝图可以独立完成某一个任务,包括模板文件,静态文件,路由都是独立的,而一个应用可以通过注册许多蓝图来进行构建。
比如我现在编写的项目,我使用的是功能式架构,具体如下:

├── server.py
├── static
│   └── novels
│       ├── css
│       │   ├── chapter.css
│       │   ├── content.css
│       │   ├── index.css
│       │   ├── main.css
│       │   └── result.css
│       ├── img
│       │   ├── bookMark.png
│       │   ├── favicon.ico
│       │   ├── read_bg.png
│       │   └── read_content.png
│       └── js
│           ├── list.js
│           └── main.js
├── template
│   └── novels
│       ├── chapter.html
│       ├── content.html
│       ├── donate.html
│       ├── feedback.html
│       ├── index.html
│       ├── main.html
│       └── result.html
└── views
    └── novels_blueprint.py

可以看到,总的templates以及静态文件还是放在一起,但是不同的blueprint则放在对应的文件夹中,还有一种分区式架构,则是将不同的templats以及static等文件夹全都放在不同的的blueprint中。
最后只要将每个单独的blueprint在主启动文件进行注册就好,比如我的这个项目:

# server.py#!/usr/bin/env pythonfrom sanic import Sanicfrom novels_search.views.novels_blueprint import bp

app = Sanic(__name__)
app.blueprint(bp)

app.run(host="0.0.0.0", port=8000, debug=True)

具体的novels_blueprint.py请点击这里

2.2.html templates编写

编写web服务,自然会涉及到html,sanic自带有html函数,但这并不能满足有些需求,故引入jinja2迫在眉睫,使用方法也很简单:

# novels_blueprint.py片段from sanic import Blueprintfrom jinja2 import Environment, PackageLoader, select_autoescape# 初始化blueprint并定义静态文件夹路径bp = Blueprint('novels_blueprint')
bp.static('/static', './static/novels')# jinjia2 configenv = Environment(
    loader=PackageLoader('views.novels_blueprint', '../templates/novels'),
    autoescape=select_autoescape(['html', 'xml', 'tpl']))def template(tpl, **kwargs):
    template = env.get_template(tpl)    return html(template.render(kwargs))    
@bp.route("/")async def index(request):
    return template('index.html', title='index')

这样,就实现了jinja2 的引入。

2.3.session

sanic对此有一个第三方插件sanic_session,用法非常简单,见官方例子如下:

import asyncio_redisfrom sanic import Sanicfrom sanic.response import textfrom sanic_session import RedisSessionInterface

app = Sanic()# Token from https://github.com/subyraman/sanic_sessionclass Redis:
    """
    A simple wrapper class that allows you to share a connection
    pool across your application.
    """
    _pool = None

    async def get_redis_pool(self):
        if not self._pool:
            self._pool = await asyncio_redis.Pool.create(
                host='localhost', port=6379, poolsize=10
            )        return self._pool


redis = Redis()# pass the getter method for the connection pool into the sessionsession_interface = RedisSessionInterface(redis.get_redis_pool, expiry=604800)@app.middleware('request')async def add_session_to_request(request):
    # before each request initialize a session
    # using the client's request
    await session_interface.open(request)@app.middleware('response')async def save_session(request, response):
    # after each request save the session,
    # pass the response to set client cookies
    await session_interface.save(request, response)@app.route("/")async def test(request):
    # interact with the session like a normal dict
    if not request['session'].get('foo'):
        request['session']['foo'] = 0

    request['session']['foo'] += 1

    response = text(request['session']['foo'])    return responseif __name__ == "__main__":
    app.run(host="0.0.0.0", port=8888, debug=True)

2.4.缓存

我在项目中主要使用redis作为缓存,使用

带上装饰器,什么都解决了。

2.5.api接口验证

在编写接口的时候,有些接口可能需要在headers中加个验证头或者token,sanic官方貌似并没有提供,解决起来很简单,可以在request时候进行验证,代码如下:

# 比如想验证一个请求的 Owllook-Api-Key值是否跟自己约定的值一样,这里写个装饰器就好from functools import wrapsfrom sanic.response import jsonfrom novels_search.config import AUTHdef authenticator(key):
    """
    
    :param keys: 验证方式 Owllook-Api-Key : Maginc Key,  Authorization : Token
    :return: 返回值
    """

    def wrapper(func):        @wraps(func)
        async def authenticate(request, *args, **kwargs):
            value = request.headers.get(key, None)            if value and AUTH[key] == value:
                response = await func(request, *args, **kwargs)                return response            else:                return json({'msg': 'not_authorized', 'status': 403})        return authenticate    return wrapper

至于使用

@api_bp.route("/bd_novels/<name>")@authenticator('Owllook-Api-Key')async def bd_novels(request, name):
    pass

具体见

3.说明

遇到什么想到什么就继续更新,具体代码[地址]
(
https://github.com/howie6879/novels-search)



作者:howie6879
链接:https://www.jianshu.com/p/28170a9cd1d4


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消