请求流

Sanic 允许你通过流来获取请求,如下。当请求结束,request.stream.get() 返回 None。只有 post、 put 和 patch 装饰器才能有流参数。

  1. from sanic import Sanic
  2. from sanic.views import CompositionView
  3. from sanic.views import HTTPMethodView
  4. from sanic.views import stream as stream_decorator
  5. from sanic.blueprints import Blueprint
  6. from sanic.response import stream, text
  7. bp = Blueprint('blueprint_request_stream')
  8. app = Sanic('request_stream')
  9. class SimpleView(HTTPMethodView):
  10. @stream_decorator
  11. async def post(self, request):
  12. result = ''
  13. while True:
  14. body = await request.stream.get()
  15. if body is None:
  16. break
  17. result += body.decode('utf-8')
  18. return text(result)
  19. @app.post('/stream', stream=True)
  20. async def handler(request):
  21. async def streaming(response):
  22. while True:
  23. body = await request.stream.get()
  24. if body is None:
  25. break
  26. body = body.decode('utf-8').replace('1', 'A')
  27. response.write(body)
  28. return stream(streaming)
  29. @bp.put('/bp_stream', stream=True)
  30. async def bp_handler(request):
  31. result = ''
  32. while True:
  33. body = await request.stream.get()
  34. if body is None:
  35. break
  36. result += body.decode('utf-8').replace('1', 'A')
  37. return text(result)
  38. async def post_handler(request):
  39. result = ''
  40. while True:
  41. body = await request.stream.get()
  42. if body is None:
  43. break
  44. result += body.decode('utf-8')
  45. return text(result)
  46. app.blueprint(bp)
  47. app.add_route(SimpleView.as_view(), '/method_view')
  48. view = CompositionView()
  49. view.add(['POST'], post_handler, stream=True)
  50. app.add_route(view, '/composition_view')
  51. if __name__ == '__main__':
  52. app.run(host='127.0.0.1', port=8000)

响应流

Sanic 允许您使用流方法将内容传输到客户端。此方法接受通过写入的 StreamingHTTPResponse 对象传递的协程回调。一个简单的例子如下:

  1. from sanic import Sanic
  2. from sanic.response import stream
  3. app = Sanic(__name__)
  4. @app.route("/")
  5. async def test(request):
  6. async def sample_streaming_fn(response):
  7. response.write('foo,')
  8. response.write('bar')
  9. return stream(sample_streaming_fn, content_type='text/csv')

这会在当你想要用流的方法将内容发送到来自外部服务的客户端的情况下变得有用,就像数据库。例如,你可以用流的方法将 asyncpg 提供的异步游标把数据记录发送到客户端:

  1. @app.route("/")
  2. async def index(request):
  3. async def stream_from_db(response):
  4. conn = await asyncpg.connect(database='test')
  5. async with conn.transaction():
  6. async for record in conn.cursor('SELECT generate_series(0, 10)'):
  7. response.write(record[0])
  8. return stream(stream_from_db)