99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python web 框架 Sanci如何使用?

發(fā)布時(shí)間:2017-07-08 16:08  回復(fù):0  查看:2706   最后回復(fù):2017-07-08 16:08  

本文和大家分享的主要是python web 框架 Sanci 相關(guān)內(nèi)容,一起來看看吧,希望對(duì)大家學(xué)習(xí)python有所幫助。

  Sanic 是一個(gè)和類Flask 的基于Python3.5+web框架,它編寫的代碼速度特別快。

  除了像Flask 以外,Sanic 還支持以異步請(qǐng)求的方式處理請(qǐng)求。這意味著你可以使用新的 async/await 語法,編寫非阻塞的快速的代碼。

  既然它說速度特別快,我們先看下官方提供的 基準(zhǔn)測試結(jié)果。

  Sanic基準(zhǔn)測試

Python web 框架 Sanci如何使用?

 這個(gè)測試的程序運(yùn)行在 AWS 實(shí)例上,系統(tǒng)是Ubuntu,只使用了一個(gè)進(jìn)程。

  Sanic 的開發(fā)者說他們的靈感來自于這篇文章 uvloop: Blazing fast Python networking 

  那我們就有必要看下uvloop是個(gè)什么庫。

  uvloop

  uvloop 是 asyncio 默認(rèn)事件循環(huán)的替代品,實(shí)現(xiàn)的功能完整,切即插即用。uvloop是用CPython 寫的,建于libuv之上。

  uvloop 可以使 asyncio 更快。事實(shí)上,它至少比 nodejsgevent 和其他 Python 異步框架要快兩倍 。基于 uvloop 的 asyncio 的速度幾乎接近了 Go 程序的速度。

  安裝 uvloop

  uvloop 還只能在 *nix 平臺(tái) 和 Python3.5+以上版本使用。

  使用pip安裝:

  pip install uvloop

  在 asyncio 代碼中使用uvloop 也很簡單:

  import asyncioimport uvloopasyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

  這得代碼使得對(duì)任何asyncio.get_event_loop() 的調(diào)用都將返回一個(gè)uvloop實(shí)例。

  詳細(xì)的uvloop 介紹可以看下原文: uvloop: Blazing fast Python networking 

  uvloopgithub地址是 https://github.com/MagicStack/uvloop 。

  現(xiàn)在我們開始學(xué)習(xí)Sanic

  安裝 Sanic

  pip install sanic

  創(chuàng)建第一個(gè) sanic 代碼

  from sanic import Sanicfrom sanic.response import text

  app = Sanic(__name__)

  @app.route("/")async def test(request):

  return text('Hello world!')

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

  運(yùn)行代碼: python main.py , 現(xiàn)在打開瀏覽器訪問 http://0.0.0.0:8000 ,你會(huì)看到 hello world! 。

  如果你熟悉Flask,你會(huì)發(fā)現(xiàn),這個(gè)語法簡直和Flask一模一樣。

  路由(Routing

  路由用于把一個(gè)函數(shù)綁定到一個(gè) URL。下面是一些基本的例子:

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

  return text('Index Page')

  @app.route('/hello')def hello():

  return text('Hello World')

  當(dāng)然,你還可以動(dòng)態(tài)的變化URL的某些部分,還可以為一個(gè)函數(shù)指定多個(gè)規(guī)則。

  變量規(guī)則

  通過把 URL 的一部分標(biāo)記為就可以在 URL 中添加變量。標(biāo)記的 部分會(huì)作為關(guān)鍵字參數(shù)傳遞給函數(shù)。通過使用,可以 選擇性的加上一個(gè)轉(zhuǎn)換器,為變量指定特定的類型,如果傳入的類型錯(cuò)誤,Sanic會(huì)拋出 NotFound 異常。請(qǐng)看下面的例子:

  from sanic.response import text

  @app.route('/tag/')async def tag_handler(request, tag):

  return text('Tag - {}'.format(tag))

  @app.route('/number/')async def integer_handler(request, integer_arg):

  return text('Integer - {}'.format(integer_arg))

  @app.route('/number/')async def number_handler(request, number_arg):

  return text('Number - {}'.format(number_arg))

  @app.route('/person/<name:[a-z]>')async def person_handler(request, name):

  return text('Person - {}'.format(name))

  @app.route('/folder/<folder_id:[a-z0-9]{0,4}>')async def folder_handler(request, folder_id):

  return text('Folder - {}'.format(folder_id))

  HTTP 請(qǐng)求類型

  默認(rèn)情況下,我們定義的URL只支持 GET 請(qǐng)求, @app.route 裝飾器提供了一個(gè)可選參數(shù) methods ,這個(gè)參數(shù)允許傳入所有HTTP 方法。

  例如:

  from sanic.response import text

  @app.route('/post', methods=['POST'])async def post_handler(request):

  return text('POST request - {}'.format(request.json))

  @app.route('/get', methods=['GET'])async def get_handler(request):

  return text('GET request - {}'.format(request.args))

  也可以簡寫為:

  from sanic.response import text

  @app.post('/post')async def post_handler(request):

  return text('POST request - {}'.format(request.json))

  @app.get('/get')async def get_handler(request):

  return text('GET request - {}'.format(request.args))

  add_route 方法

  除了 @app.route 裝飾器,Sanic 還提供了 add_route 方法。

  @app.route 只是包裝了 add_route 方法。

  from sanic.response import text

  # Define the handler functionsasync def handler1(request):

  return text('OK')

  async def handler2(request, name):

  return text('Folder - {}'.format(name))

  async def person_handler2(request, name):

  return text('Person - {}'.format(name))

  # Add each handler function as a route

  app.add_route(handler1, '/test')

  app.add_route(handler2, '/folder/')

  app.add_route(person_handler2, '/person/<name:[a-z]>', methods=['GET'])

  URL 構(gòu)建

  如果可以匹配URL,那么Sanic可以生成URL嗎?當(dāng)然可以,url_for() 函數(shù)就是用于構(gòu)建指定函數(shù)的URL的。它把函數(shù)名稱作為第一個(gè)參數(shù),其余參數(shù)對(duì)應(yīng)URL中的變量,例如:

  @app.route('/')async def index(request):

  # generate a URL for the endpoint `post_handler`

  url = app.url_for('post_handler', post_id=5)

  # the URL is `/posts/5`, redirect to it

  return redirect(url)

  @app.route('/posts/')async def post_handler(request, post_id):

  return text('Post - {}'.format(post_id))

  未定義變量會(huì)作為URL的查詢參數(shù):

  url = app.url_for('post_handler', post_id=5, arg_one='one', arg_two='two')# /posts/5?arg_one=one&arg_two=two

  # 支持多值參數(shù)url = app.url_for('post_handler', post_id=5, arg_one=['one', 'two'])# /posts/5?arg_one=one&arg_one=two

  使用藍(lán)圖(Blueprint

  Sanic也提供了和Flask 類似的 Blueprint

  Blueprint有以下用途:

 ?。?nbsp;把一個(gè)應(yīng)用分解為一套藍(lán)圖。這是針對(duì)大型應(yīng)用的理想方案:一個(gè)項(xiàng)目可以實(shí)例化一個(gè) 應(yīng)用,初始化多個(gè)擴(kuò)展,并注冊(cè)許多藍(lán)圖。

  . 在一個(gè)應(yīng)用的 URL 前綴和(或)子域上注冊(cè)一個(gè)藍(lán)圖。 URL 前綴和(或)子域的參數(shù) 成為藍(lán)圖中所有視圖的通用視圖參數(shù)(缺省情況下)。

 ?。?nbsp;使用不同的 URL 規(guī)則在應(yīng)用中多次注冊(cè)藍(lán)圖。

 ?。?nbsp;通過藍(lán)圖提供模板過濾器、靜態(tài)文件、模板和其他工具。藍(lán)圖不必執(zhí)行應(yīng)用或視圖 函數(shù)。

  blueprint 示例

  from sanic import Sanicfrom sanic.response import jsonfrom sanic import Blueprint

  bp = Blueprint('my_blueprint')

  @bp.route('/')async def bp_root(request):

  return json({'my': 'blueprint'})

  app = Sanic(__name__)

  app.blueprint(bp)

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

  Sanic 使用 app.blueprint() 方法注冊(cè)blueprint。

  使用藍(lán)圖注冊(cè)全局中間件

  @bp.middlewareasync def print_on_request(request):

  print("I am a spy")

  @bp.middleware('request')async def halt_request(request):

  return text('I halted the request')

  @bp.middleware('response')async def halt_response(request, response):

  return text('I halted the response')

  使用藍(lán)圖處理異常

  @bp.exception(NotFound)def ignore_404s(request, exception):

  return text("Yep, I totally found the page: {}".format(request.url))

  使用藍(lán)圖處理靜態(tài)文件

  第一個(gè)參數(shù)指向當(dāng)前的Python

  第二個(gè)參數(shù)是靜態(tài)文件的目錄

  bp.static('/folder/to/serve', '/web/path')

  使用url_for

  如果要?jiǎng)?chuàng)建頁面鏈接,可以和通常一樣使用 url_for() 函數(shù),只是要把藍(lán)圖名稱作為端點(diǎn)的前綴,并且用一個(gè)點(diǎn)( )來 分隔:

  @blueprint_v1.route('/')async def root(request):

  url = app.url_for('v1.post_handler', post_id=5) # --> '/v1/post/5'

  return redirect(url)

  @blueprint_v1.route('/post/')async def post_handler(request, post_id):

  return text('Post {} in Blueprint V1'.format(post_id))

  操作請(qǐng)求數(shù)據(jù)

  對(duì)于web 應(yīng)用來說對(duì)客戶端向服務(wù)器發(fā)送的數(shù)據(jù)做出相應(yīng)很重要,在Sanic中由傳入的參數(shù) request來提供請(qǐng)求信息。

  為什么不像Flask 一樣提供一個(gè)全局變量 request?

  Flask 是同步請(qǐng)求,每次請(qǐng)求都有一個(gè)獨(dú)立的新線程來處理,這個(gè)線程中也只處理這一個(gè)請(qǐng)求。而Sanic是基于協(xié)程的處理方式,一個(gè)線程可以同時(shí)處理幾個(gè)、幾十個(gè)甚至幾百個(gè)請(qǐng)求,把request作為全局變量顯然會(huì)比較難以處理。

  Request 對(duì)象常用參數(shù)有

  jsonany) json body

  from sanic.response import json

  @app.route("/json")def post_json(request):

  return json({ "received": True, "message": request.json })

  argsdict) URL請(qǐng)求參數(shù)

  ?key1=value1&key2=value2 將轉(zhuǎn)變?yōu)?/span>

  {'key1': ['value1'], 'key2': ['value2']}

  raw_argsdict) 和args 類似

  ?key1=value1&key2=value2 將轉(zhuǎn)變?yōu)?/span>

  {'key1': 'value1', 'key2': 'value2'}

  formdict)處理 POST 表單請(qǐng)求,數(shù)據(jù)是一個(gè)字典

  bodybytes)處理POST 表單請(qǐng)求,數(shù)據(jù)是一個(gè)字符串

  其他參數(shù)還有:

 ?。?file

  . ip

 ?。?app

  . url

 ?。?scheme

 ?。?path

  . query_string

  關(guān)于響應(yīng)

  Sanic使用response 函數(shù)創(chuàng)建響應(yīng)對(duì)象。

  . 文本 response.text('hello world')

 ?。?html response.html(' 

hello world

')

 ?。?json response.json({'hello': 'world'})

  . file response.file('/srv/www/hello.txt')

 ?。?streaming

  from sanic import response

  @app.route("/streaming")async def index(request):

  async def streaming_fn(response):

  response.write('foo')

  response.write('bar')

  return response.stream(streaming_fn, content_type='text/plain')

  . redirect response.file('/json')

 ?。?raw response.raw('raw data')

 ?。?nbsp;如果想修改響應(yīng)的headers可以傳入headers 參數(shù)

  from sanic import response

  @app.route('/json')def handle_request(request):

  return response.json(

  {'message': 'Hello world!'},

  headers={'X-Served-By': 'sanic'},

  status=200

  )

  配置管理

  應(yīng)用總是需要一定的配置的。根據(jù)應(yīng)用環(huán)境不同,會(huì)需要不同的配置。比如開關(guān)調(diào)試 模式、設(shè)置密鑰以及其他依賴于環(huán)境的東西。

  Sanic 的設(shè)計(jì)思路是在應(yīng)用開始時(shí)載入配置。你可以在代碼中直接硬編碼寫入配置,也可以使用配置文件。

  不管你使用何種方式載入配置,都可以使用 Sanic 的 config 屬性來操作配置的值。 Sanic 本身就使用這個(gè)對(duì)象來保存 一些配置,擴(kuò)展也可以使用這個(gè)對(duì)象保存配置。同時(shí)這也是你保存配置的地方。

  配置入門

  config 實(shí)質(zhì)上是一個(gè)字典的子類,可以像字典一樣操作:

  app = Sanic('myapp')

  app.config.DB_NAME = 'appdb'

  app.config.DB_USER = 'appuser'

  也可以一次更新多個(gè)配置:

  db_settings = {

  'DB_HOST': 'localhost',

  'DB_NAME': 'appdb',

  'DB_USER': 'appuser'

  }

  app.config.update(db_settings)

  從對(duì)象導(dǎo)入配置

  import myapp.default_settings

  app = Sanic('myapp')

  app.config.from_object(myapp.default_settings)

  使用配置文件

  如果把配置放在一個(gè)單獨(dú)的文件中會(huì)更有用。理想情況下配置文件應(yīng)當(dāng)放在應(yīng)用包的 外面。這樣可以在修改配置文件時(shí)不影響應(yīng)用的打包與分發(fā)

  常見用法如下:

  app = Sanic('myapp')

  app.config.from_envvar('MYAPP_SETTINGS')

  首先從 myapp.default_settings 模塊載入配置,然后根據(jù) MYAPP_SETTINGS 環(huán)境變量所指向的文件的內(nèi)容重載配置的值。在 啟動(dòng)服務(wù)器前,在 Linux 或 OS X 操作系統(tǒng)中,這個(gè)環(huán)境變量可以在終端中使用 export 命令來設(shè)置:

  $ export MYAPP_SETTINGS=/path/to/config_file

  $ python myapp.py

  部署

  Sanic 項(xiàng)目還不是特別成熟,現(xiàn)在部署比較簡陋。對(duì)Gunicorn的支持也不完善。

  現(xiàn)在說下我的部署方式

  使用 supervisord 部署

  supervisord 配置文件: https://github.com/gusibi/momo/blob/master/supervisord.conf

  啟動(dòng) 方式

  supervisord -c supervisor.conf

  總結(jié)

  試用了下Sanic,把之前的一個(gè)聊天機(jī)器人從Flask 改成了 Sanic。不得不說,如果你有Flask經(jīng)驗(yàn),大致看一下Sanic文檔就可以直接上手了。

  并且Sanic 的速度比Flask 快很多,只是Sanic配套的包還是太少,用于生產(chǎn)環(huán)境有一定的風(fēng)險(xiǎn)。

 

 

來源:伯樂在線

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?