Python 的 web 相关库杂录

随手找的一些模型部署简单例子.

uWSGI

uWSGI, pronounced “mu wiz gee” (u or $\mu$ whiskey), is a Web Server Gateway Interface (WSGI) server implementation that is typically used to run Python web applications.

可以参考 uWSGI - Full Stack Python 收集的资源. Full Stack Python 是很好的资源站.

Gunicorn

Green Unicorn, commonly shortened to “Gunicorn”, is a Web Server Gateway Interface (WSGI) server implementation that is commonly used to run Python web applications.

Use Gunicorn, unless you are deploying on Windows, in which case use mod_wsgi.

uWSGI 很多功能与 Nginx 等部件重复, 文档也很杂乱 (开发者承认很难写). Gunicorn 简单效果好.

gevent

gevent is a coroutine-based Python networking library that uses greenlet to provide a high-level synchronous API on top of the libev or libuv event loop.

A monkey patch (also spelled monkey-patch, MonkeyPatch) is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.) without altering the original source code.

Ngnix

Nginx, pronounced “engine-X”, is the second most common web server among the top 100,000 websites. Nginx also functions well as a reverse proxy to handle requests and pass back responses for Python WSGI servers or even other web servers such as Apache.

Flask

Flask is a Python web framework built with a small core and easy-to-extend philosophy.

基本用法没什么好说的. 此外有个自动生成 Swagger UI 的包 Flask-RESTX. Flask-RESTX is a community driven fork of Flask-RESTPlus (后者很久没维护了, 前者也有一段时间不怎么维护了).

部署到生产时官方 tutorial 用了 Waitress; 这里 介绍了各种常见 WSGI server 部署 Flask 的例子.,

FastAPI

Celery

Celery is a task queue implementation for Python web applications used to asynchronously execute work outside the HTTP request-response cycle.

异步基本就用这个库. Celery 命名 来源 于, 它把数据喂给 RabbitMQ.

把应用迁移到使用 Celery 不用改什么代码, 工作量主要在配置上.

一些资源 (Show more »)

Full Stack Python

其他看到的

进一步解释 Celery 机制

除了一开始的 tutorial, 官方 userguide 建议先看 tasks.

Celery 启动后先注册任务, 可以用 --loglevel=DEBUG, 搜索 tasks, 看任务有没有注册, 注册了哪些 (autodiscover_tasks 中可以指定搜索路径). 在代码中实际使用时, 函数路径必须和注册的任务名相同 (x.y.z, 注意相对 import).

其他

Flask-RESTX demo

需要注意的是, 如果开了 .expect(validate=True), 发送不合法的请求后, Swagger UI 上不会有任何提示. 这是 Swagger UI 的一个 “bug”, 见这个 issue.

import flask
import flask_restx
from flask import request
from flask_restx import fields

app = flask.Flask(__name__)
api = flask_restx.Api(app=app, title='app title', version='2.3.3', description='app desc')

CONFERENCES_DESC = """
Conference operations

Markdown is supported.
"""
ns_conf = api.namespace(name='conferences', description=CONFERENCES_DESC)
model_conf_input = ns_conf.model(
    name='my_model',
    model={
        'name': fields.String(
            example='C7', description='name whatever', title='field title',
            min_length=1, max_length=10, pattern=r'[A-Z][0-9]', required=True
        ),
        # the default example is the first element of the enum argument ('A' in this case)
        'type': fields.String(enum=['A', 'B', 'C']),
        'nums': fields.List(
            fields.Integer(min=0, max=100),
            min_items=0, max_items=10, description='list of integers'
        ),
        'bool': fields.Boolean(),
    },
    strict=True
)
model_conf_response = ns_conf.model(name='response', model={
    'name': fields.String(description='haha'),
    'nums': fields.List(fields.Integer())
})


@ns_conf.route("/")
class ConferenceList(flask_restx.Resource):
    # `.doc(body=...)` or `.expect(...)` for input
    # `.doc(model=...)` for response
    @ns_conf.expect(model_conf_input, validate=True)
    @ns_conf.param('payload', 'some description goes here', _in='body')
    @ns_conf.response(200, 'Success', model_conf_response)
    @ns_conf.response(400, 'Validation Error')
    def post(self):
        """
        random example

        **markdown is also supported in docstring**
        """
        name = request.json.get('name')
        nums = request.json.get('nums')
        return {
            'name': name,
            'nums': nums
        }


@ns_conf.route("/<int:id>")
class Conference(flask_restx.Resource):
    @ns_conf.doc(params={'id': 'An ID'})
    def get(self, id):
        return id


if __name__ == '__main__':
    app.run(debug=True)

Memo