Python讓你的Web應用程飛起來全家桶之Sanic

1、前言

爲何要用Sanic,請見 讓你的Python(Web應用)飛起來,(異步/協程)全家桶html

廢話很少講,直接進入正題,我會按照正常的Web應用程序架構來說Sanic的用法python

2、進入正題

基本操做

  1. 安裝Sanic

pip install sanicredis

  1. 導入Sanic
from sanic import Sanic
app = Sanic(__name__)
複製代碼

中間件(Middleware And Listeners)

服務啓動以前數據庫

@app.listener('before_server_start')
async def start_connection(app, loop):
    # 執行一些初始化任務
    # 例如初始化 Redis 鏈接池
    await RedisPool.init_redis_conn_pool(loop)
複製代碼

服務中止以前json

@app.listener('after_server_stop')
async def start_connection(app, loop):
    # 執行一些備份、應急、關閉任務
    # 例如關閉鏈接池
    await RedisPool.close_redis_conn_pool()
    await close_connection(app, loop)
複製代碼

請求(Request)中間件api

@app.middleware('request')
async def add_tokrn_to_request(request):
    # 每次請求會通過此方法,能夠作一些對request的處理
    # 例如添加token,secret,token
    await session_interface.open(request)
複製代碼

響應(Response)中間件瀏覽器

@app.middleware('response')
async def save_session(request, response):
    logger = logging.getLogger('response')
    # 每次服務器響應會通過此方法,能夠作一些異常,cookie,logger等的處理
    # 例如寫入cookie,記錄用戶日誌
    await session_interface.save(request, response)
複製代碼

藍圖(Blueprint)

相似Flask,用來組織應用程序,也就是大多數咱們mvc模式中的controller,服務器

  1. 首先聲明一個BP
order_bp = Blueprint('orders', url_prefix='v1/api/order')
# url_prefix:定義路由修正,
# 例如當前藍圖下你定義了一個 query/id 的路由,那麼你應該這樣訪問它 v1/api/order/query/id
複製代碼
  1. 在主程序中(main.py)引用
from controller.order_controller import order_bp
app.blueprint(order_bp)
# 這樣order_bp就被註冊到sanic中,能夠經過瀏覽器 http://example.com/v1/api/order/query/id 訪問
複製代碼
  1. 使用藍圖處理異常
@bp.exception(NotFound)
def ignore_404(request, exception):
    return text("Yep, I totally found the page: {}".format(request.url))
複製代碼

路由(Routing)

# GET 路由參數的方式
@order_bp.route('/delete/<oid:int>', methods=['GET'])
async def delete_order(request, oid):
    result = await OrderModel().del_order_by_id(oid)
    if result:
        return json({'status': 'ok', 'result': result})
    return json({'status': 'fail', 'errmsg': '獲取數據失敗'})
複製代碼
# Get params的方式
@service_bp.route('/message/send', methods=['GET'])
async def send_message(request):
    uuid = request.args['uuid'][0]
    page = request.args['page'][0]
    result = await MessageService().send_message_2_user(uuid,page)
    if result:
        return json({'status': 'ok', 'result': result})
    return json({'status': 'fail', 'errmsg': '獲取數據失敗'})

    return raw(result)
複製代碼
# 修改價格
@order_bp.route('/price/modify', methods=['POST'])
async def price_modify(request):
    order_id = request.json['order_id']
    price = request.json['price']
    postage = request.json['postage']
    show_price = request.json['show_price']
    is_shipping = request.json['is_shipping']
    result = await OrderModel().modify_price(order_id, price, postage, show_price, is_shipping)

    if result:
        return json({'status': 'ok', 'result': result})
    return json({'status': 'fail', 'errmsg': '獲取數據失敗'})
複製代碼

響應類型

from sanic.response import json
# text
response.text('hello world')
# html
response.html('<p>hello world</p>')
# json
response.json({'hello': 'world'})
# file
response.file('/srv/www/hello.txt')
# stream
response.stream(stream_ctx, content_type='text/plain')
複製代碼

若是我想在Sanic啓動以後額外運行任務怎麼辦?cookie

app.add_task(notify_server_started())
app.add_task(notify_html_spider())
複製代碼

3、啓動Sanic服務

if __name__ == "__main__":
    app.add_task(notify_server_started())
    app.add_task(notify_html_spider())
    app.run(host="0.0.0.0", port=settings.PORT, workers=settings.workers, debug=settings.DEBUG, access_log=True)
複製代碼

在啓動時能夠傳入一些參數,其餘的都是字面意思,很好理解,這裏講一下 Workerssession

workers 接受 integer 類型,默認爲1,傳入4意味着Sanic會爲你複製四份,建立四個進程來運行你的Sanic App

如圖

多進程狀態下,路由會進行自動分配,從而增長吞吐量,workers的個數依據自身服務器性能而定,若是建立太多會出現佔用狀況,一樣多進程模式下,你的數據庫鏈接或者數據庫鏈接池的數量也要適當調大,不然會出現鏈接數過多而拒絕鏈接的狀況

4、獲獎感言

Sanic的介紹就這麼多,只是一個基本入門,至於其餘相似訂閱發佈監聽等等功能你們能夠移步 Sanic官網 進行學習和查閱

下期我可能會聯合Sanic講解關於異步Redis(aioredis)的使用,例子打算用相似訂單倒計時的功能,結合redis的訂閱發佈通知來說

相關文章
相關標籤/搜索