《SANIC中文用户指南》—读书笔记

本文档详细介绍了Sanic,一个利用async/await提升性能的Python Web框架,涵盖了安装、应用创建、配置定制、中间件、路由、WebSocket支持及高级特性等内容。

SANIC 中文用户指南
SANIC API文档
在这里插入图片描述
Sanic是Python3.7+Web服务器和Web框架,旨在提高性能。它允许使用Python3.5中添加async/await 语法,使代码有效的避免阻塞从而达到提升响应速度的目的。

Sanic提供一种简单且快速,集创建和启动于一体的方法,来实现一个易于修改和拓展的HTTP服务。

  • 安装
pip install sanic
  • 应用
#server.py
from sanic import Sanic
from sanic.response import text

app = Sanic('MyHelloWorldApp')

@app.get('/')
async def hello_world(request):
    return text('Hello, world.')
  • 运行
sanic server.app

入门

Sanic应用(Sanic Application)

  • 实例(Instance)
    Sanic()是最基础的组成部分,在server.py的文件中将其实例化,文件名不是必须的,但是推荐使用server.py作为名称来实例化Sanic对象。

    # /path/to/server.py
    
    from sanic import Sanic
    
    app = Sanic('MyHelloWorldApp')
    
  • 应用上下文(Application context)
    大多数应用程序都需要跨代码库的不同部分共享/重用数据或对象。最常见的例子是数据库连接。v21.3版本中引入了应用级的上下文对象,且使用方法与请求上下文一致,有效的避免了命名冲突可能导致的潜在问题。

    # Correct way to attach objects to the application
    app = Sanic('MyApp')
    app.ctx.db = Database()
    
  • App注册表(App)
    当实例化一个Sanic对象之后,可以随时通过Sanic注册表来获取该对象。如果获取的对象不存在,通过添加force_create参数主动创建一个同名的Sanic对象并返回,如果不设置该参数,默认情况下会抛出SanicException异常。如果只有一个Sanic实例被注册了,不传人任何参数将返回该实例。

    # /path/to/server.py
    from sanic import Sanic
    app = Sanic('my_awesome_server')
    app = Sanic.get_app('my_awesome_server')
    
    app = Sanic.get_app('non-existing', force_create=True,)
    
    Sanic('My only app')
    app = Sanic.get_app()
    
  • 配置(Configuration)
    Sanic将配置保存在Sanic对象的config属性中。可以使用属性操作或字典操作的方式来修改配置。

    app = Sanic('myapp')
    app.config.DB_NAME = 'appdb'
    app.config.['DB_USER'] = 'appuser'
    
    db.settings = {
         
         
       'DB_HOST' : 'localhost',
       'DB_NAME' : 'appdb',
       'DB_USER' : 'appuser'
    }
    app.config.update(db_settings)
    
  • 自定义(Customization)
    Sanic应用在实例化时可以根据个人需求以多种方式进行定制。

    • 自定义配置(Custom configuration)
      自定义配置就是将自己的配置对象直接传递到Sanic实例中。如果使用了自定义配置对象类,建议将自定义类继承Sanic的Config类,以保持与父类行为一致。可以调用父类方法来添加属性。

      from sanic.config import Config
      class MyConfig(Config):
          FOO = 'bar'
      app = Sanic(..., config=MyConfig())
      
      from sanic import Sanic, text
      from sanic.config import Config
      class TomlConfig(Config):
          def __init__(self, *args, path:str, **kwargs):
              super().__init__(*args, **kwargs)
              with open(path, 'r') as f:
                  self.apply(toml.load(f))
          def apply(self, config):
              self.update(self._to_uppercase(config))
          def _to_uppercase(self, obj:Dict[str, Any])->Dict[str, Any]:
              retval:Dict[str, Any] = {
             
             }
              for key, value in obj.items():
                  upper_key = key.upper()
                  if isinstance(value, list):
                      retval[upper_key] = [self._to_uppercase(item) for item in value]
                  elif isinstance(value, dict):
                      retval[upper_key] = self._to_uppercase(value)
                  else:
                      retval[upper_key] = value
              return retval
      toml_config = TomlConfig(path='/path/to/config.toml')
      app = Sanic(toml_config.APP_NAME, config=toml_config)
      
    • 自定义上下文(Custom context)
      默认情况下,应用程序上下文是一个SimpleNamespace实例,它允许在上面设置任何想要的属性。当然,也可以使用其他对象来代替。

    • 自定义请求(Custom requests)

      import time
      from sanic import Request, Sanic, text
      class NanoSecondRequest(Request):
          @classmethod
          def generate_id(*_):
              return time.time_ns()
      app = Sanic(..., request_class=NanoSecondRequest)
      @app.get('/')
      async def handler(request):
          return text(str(request.id))
      
    • 自定义错误响应函数(Custom error handler)

      from sanic.handlers import ErrorHandler
      class CustomErrorHandler(ErrorHandler):
          def default(self, request, exception):
              '''
              handles errors that have no error handlers assigned
              '''
              # You custom error handling logic...
              return super().default(request, exception)
      app = Sanic(..., error_handler = CustomErrorHandler())
      

响应函数(Handlers)

在Sanic中,响应函数可以是任何一个可调用程序,它至少是一个request实例作为参数,并返回一个HTTPResponse实例或一个执行其他操作的协同程序作为响应。

它既可以是一个普通函数,也可以是一个异步的函数。它的工作是响应指定端点的访问,并执行一些指定的操作,是承载业务逻辑代码的地方。

def i_am_a_handler(request):
    return HTTPResponse()
async def i_am_ALSO_a_handler(request):
    return HTTPResponse()
from sanic.response import text
@app.get('/foo')
async def foo_handler(request):
    return text('I said foo!')

带完整注释的响应函数

from sanic.response import HTTPResponse, text
from sanic.request import Request

@app.get('/typed')
async def typed_handler(request:Request)->HTTPResponse:
    return text('Done.')

请求(Request)

  • 请求体(Body)
    在这里插入图片描述

  • 上下文(Context)

    • 请求上下文(Request context)
      request.ctx对象是存储请求相关信息的地方。通常用来存储服务端通过某些验证后需要临时存储的身份认证信息以及专有变量等内容。最典型的用法就是将从数据库获取的用户对象存储在request.ctx中,所有该中间件之后的其他中间件以及请求期间的处理程序都可以对此进行访问。

      @app.middleware('request')
      async def run_before_handler(request):
          request.ctx.user = await fetch_user_by_token(request.token)
      @app.get('/hi')
      async def hi_my_name_is(request):
          return text('Hi, my name is {}'.format(request.ctx.user.name))
      
    • 连接上下文(Connection context)
      通常情况下,应用程序需要向同一个客户端提供多个并发(或连续)的请求。这种情况通常发生在需要查询多个端点来获取数据的渐进式网络应用程序中。在HTTP协议要求通过keep alive请求来减少频繁连接所造成的时间浪费。当多个请求共享一个连接时,Sanic将提供一个上下文对象来允许这些请求共享状态。

      @app.on_request
      async def increment_foo(request):
          if not hasattr(request.conn_info.ctx, 'foo'):
              rquest.conn_info.ctx.foo = 0
          request.conn_info.ctx.foo += 1
      @app.get('/')
      async def count_foo(request):
          return text(f'request.conn_info.ctx.foo={
               
               request.conn_info.ctx.foo}')
      
    <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值