python sanic
by Davit Tovmasyan
由Davit Tovmasyan
如何使用Python和Sanic使代码快速异步 (How to make your code fast and asynchronous with Python and Sanic)
Hello everybody. In this article I’ll talk about building simple asynchronous projects with the Sanic framework.
大家好。 在本文中,我将讨论使用Sanic框架构建简单的异步项目。
介绍 (Introduction)
Sanic is a very flask-like open-source Python web server and web framework with more than 10K stars that’s written to go fast. It allows the usage of async/await
syntax added in Python 3.5 (read more), which makes your code non-blocking and speedy.
桑尼奇 是一个非常类似烧瓶的开源Python Web服务器和Web框架,具有超过1万颗星 ,并且编写得很快。 它允许使用Python 3.5中添加的async/await
语法( 更多信息 ),这使您的代码无阻塞且快速。
Sanic has pretty good documentation and it’s maintained by the community, for the community.
Sanic有相当不错的文档 ,由社区维护,以供社区使用。
The goal of the project is to provide a simple way to get a highly performant HTTP server up and running that is easy to build, to expand, and ultimately to scale.
该项目的目标是提供一种简单的方法来启动并运行高性能HTTP服务器,并且易于构建,扩展和最终扩展。
要求 (Requirements)
Before we start, let’s install some packages and make sure that we have everything ready for the development of this project.
在开始之前,让我们安装一些软件包,并确保我们已准备好一切以开发该项目。
Note: Source code is available in my github.com repository. For each step there is a corresponding commit.
注意:源代码可在我的github.com存储库中找到。 对于每个步骤,都有一个相应的提交。
先决条件: (Prerequisites:)
- Python3.6+ Python3.6 +
pipenv (you can use any other package installer)
pipenv (您可以使用任何其他软件包安装程序)
PostgreSQL (for database, can also be MySQL or SQLite)
PostgreSQL (对于数据库,也可以是MySQL或SQLite)
包装方式: (Packages:)
secure is a lightweight package that adds optional security headers and cookie attributes for Python web frameworks.
secure是一个轻量级软件包,为Python Web框架添加了可选的安全标头和cookie属性。
environs is a Python library for parsing environment variables. It allows you to store configuration separate from your code, as per The Twelve-Factor App methodology.
environs是用于解析环境变量的Python库。 根据十二要素应用程序方法,它使您可以将配置与代码分开存储。
sanic-envconfig is and extension that helps you bring command line & environment variables into your Sanic config.
sanic-envconfig是该扩展程序,可以帮助您将命令行和环境变量引入Sanic配置。
databases is a Python package that allows you to make queries using the powerful SQLAlchemy Core expression language, and provides support for PostgreSQL, MySQL, and SQLite.
数据库是一个Python软件包,可让您使用功能强大的SQLAlchemy Core表达式语言进行查询,并提供对PostgreSQL,MySQL和SQLite的支持。
Let’s create an empty directory and initialize an empty Pipfile
there.
让我们创建一个空目录并在那里初始化一个空Pipfile
。
pipenv -- python python3.6
Install all necessary packages using pipenv commands below.
使用下面的pipenv命令安装所有必需的软件包。
pipenv install sanic secure environs sanic-envconfig
For database:
对于数据库:
pipenv install databases[postgresql]
Choices are postgresql, mysql, sqlite.
选择是 PostgreSQL,MySQL,SQLite。
结构体 (Structure)
Now let’s create some files and folders where we will write our actual code.
现在,让我们创建一些文件和文件夹,在其中编写实际代码。
├── .env├── Pipfile├── Pipfile.lock├── setup.py└── project ├── __init__.py ├── __main__.py ├── main.py ├── middlewares.py ├── routes.py ├── settings.py └── tables.py
We will use the setup.py
file to make the project
folder available as a package in our code.
我们将使用setup.py
文件使project
文件夹作为程序包中的程序包可用。
from setuptools import setupsetup( name='project',)
Installing…
正在安装…
pipenv install -e .
In the .env
file, we’ll store some global variables like the database connection URL.
在.env
文件中,我们将存储一些全局变量,例如数据库连接URL。
__main__.py
is created for making our project
package executable from the command-line.
创建__main__.py
是为了使我们的project
包可从命令行执行。
pipenv run python -m project
初始化 (Initialization)
Let’s do our first call in __main__.py file.
让我们在__main__.py文件中进行第一个调用。
from project.main import initinit()
This is the beginning of our application. Now we need to create the init
function inside of main.py file.
这是我们应用程序的开始。 现在我们需要在main.py文件内部创建init
函数。
from sanic import Sanicapp = Sanic(__name__)def init(): app.run(host='0.0.0.0', port=8000, debug=True)
Simply creating the app from the Sanic class we can run it specifying host, port and optional debug keyword argument.
只需从Sanic类创建应用程序,即可指定host , port和可选的debug关键字参数来运行它。
Running…
跑步中...
pipenv run python -m project
This is how a successful output should look in your Sanic app. If you open http://0.0.0.0:8000 on your browser you’ll see
这就是在Sanic应用程序中成功输出的外观。 如果您在浏览器中打开http://0.0.0.0:8000 ,则会看到
Error: Requested URL / not found
错误:请求的网址/未找到
We haven’t created any routes yet, so it’s fine for now. We will add some routes below.
我们尚未创建任何路线 ,因此目前还可以。 我们将在下面添加一些路线。
设定值 (Settings)
Now we can modify the environment and settings. We need to add some variables in the .env file, read them, and pass to Sanic app config.
现在我们可以修改环境和设置。 我们需要在.env文件中添加一些变量,读取它们,然后传递给Sanic应用程序配置。
.env file.
.env 文件。
DEBUG=TrueHOST=0.0.0.0POST=8000
Configuration…
组态…
from sanic import Sanic
from environs import Envfrom project.settings import Settings
app = Sanic(__name__)
def init(): env = Env() env.read_env() app.config.from_object(Settings) app.run( host=app.config.HOST, port=app.config.PORT, debug=app.config.DEBUG, auto_reload=app.config.DEBUG, )
settings.py file.
settings.py 文件。
from sanic_envconfig import EnvConfigclass Settings(EnvConfig): DEBUG: bool = True HOST: str = '0.0.0.0' PORT: int = 8000
Please note that I’ve added an optional auto_reload argument which will activate or deactivate the Automatic Reloader.
请注意,我添加了一个可选的auto_reload参数,它将激活或停用自动重新加载器。
数据库 (Database)
Now it’s time to setup a database.
现在是时候设置数据库了。
One little note about the databases package before we go ahead:
在继续之前,请先对数据库包进行一点说明:
databases package uses asyncpg which is an asynchronous interface library for PostgreSQL. It’s pretty fast. See results below.
数据库包使用asyncpg 这是PostgreSQL异步接口库。 非常快。 参见下面的结果。
We will use two of Sanic’s listeners where we will specify database connect and disconnect operations. Here are the listeners that we are going to use:
我们将使用Sanic的两个侦听器 ,在其中指定数据库连接和断开连接操作。 这是我们将要使用的监听器:
after_server_start
after_server_start
after_server_stop
after_server_stop
main.py file.
main.py 文件。
from sanic import Sanic
from databases import Database
from environs import Envfrom project.settings import Settings
app = Sanic(__name__)
def setup_database(): app.db = Database(app.config.DB_URL) @app.listener('after_server_start') async def connect_to_db(*args, **kwargs): await app.db.connect() @app.listener('after_server_stop') async def disconnect_from_db(*args, **kwargs): await app.db.disconnect()
def init(): env = Env() env.read_env() app.config.from_object(Settings)
setup_database()
app.run( host=app.config.HOST, port=app.config.PORT, debug=app.config.DEBUG, auto_reload=app.config.DEBUG, )
Once more thing. We need to specify DB_URL in project settings and environment.
再说一遍。 我们需要在项目设置和环境中指定DB_URL 。
.env file.
.env 文件。
DEBUG=TrueHOST=0.0.0.0POST=8000DB_URL=postgresql://postgres:postgres@localhost/postgres
And settings.py file.
和settings.py文件。
from sanic_envconfig import EnvConfigclass Settings(EnvConfig): DEBUG: bool = True HOST: str = '0.0.0.0' PORT: int = 8000 DB_URL: str = ''
Make sure that DB_URL is correct and your database is running. Now you can access to database using app.db. See more detailed information in the next section.
确保DB_URL正确并且数据库正在运行。 现在,您可以使用app.db访问数据库。 在下一部分中查看更多详细信息。
桌子 (Tables)
Now we have a connection to our database and we can try to do some SQL queries.
现在我们已经连接到数据库,我们可以尝试执行一些SQL查询。
Let’s declare a table in tables.py file using SQLAlchemy.
让我们使用SQLAlchemy在table.py文件中声明一个表。
import sqlalchemymetadata = sqlalchemy.MetaData()books = sqlalchemy.Table( 'books', metadata, sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True), sqlalchemy.Column('title', sqlalchemy.String(length=100)), sqlalchemy.Column('author', sqlalchemy.String(length=60)),)
Here I assume that you already have a migrated database with a books table in it. For creating database migrations, I recommend that you use Alembic which is a lightweight and easy-to-use tool that you can use with the SQLAlchemy Database Toolkit for Python.
在这里,我假设您已经有一个迁移的数据库,其中包含一个books表。 为了创建数据库迁移,我建议您使用Alembic ,它是一种轻量级且易于使用的工具,可以与SQLAlchemy Database Toolkit for Python一起使用。
Now we can use any SQLAlchemy core queries. Check out some examples below.
现在我们可以使用任何SQLAlchemy核心查询。 在下面查看一些示例。
# Executing manyquery = books.insert()values = [ {"title": "No Highway", "author": "Nevil Shute"}, {"title": "The Daffodil", "author": "SkyH. E. Bates"},]await app.db.execute_many(query, values)# Fetching multiple rowsquery = books.select()rows = await app.db.fetch_all(query)# Fetch single rowquery = books.select()row = await app.db.fetch_one(query)
路线 (Routes)
Now we need to setup routes. Let’s go to routes.py and add a new route for books.
现在我们需要设置路线。 让我们转到routes.py ,为书添加一条新路线。
from sanic.response import json
from project.tables import books
def setup_routes(app): @app.route("/books") async def book_list(request): query = books.select() rows = await request.app.db.fetch_all(query) return json({ 'books': [{row['title']: row['author']} for row in rows] })
Of course we need to call setup_routes in init to make it work.
当然,我们需要在init中调用setup_routes使其起作用。
from project.routes import setup_routes
app = Sanic(__name__)
def init(): ... app.config.from_object(Settings) setup_database() setup_routes(app) ...
Requesting…
正在请求…
$ curl localhost:8000/books{"books":[{"No Highway":"Nevil Shute"},{"The Daffodil":"SkyH. E. Bates"}]}
中间件 (Middlewares)
What about checking the response headers and seeing what we can add or fix there?
如何检查响应头并查看我们可以在此处添加或修复的内容呢?
$ curl -I localhost:8000Connection: keep-aliveKeep-Alive: 5Content-Length: 32Content-Type: text/plain; charset=utf-8
As you can see we need some security improvements. There are some missing headers such as X-XSS-Protection, Strict-Transport-Security… so let’s take care of them using a combination of middlewares and secure packages.
如您所见,我们需要一些安全性改进。 缺少一些标头,例如X-XSS-Protection,Strict-Transport-Security … 因此,让我们结合使用中间件和安全软件包来照顾它们。
middlewares.py file.
middlewares.py 文件。
from secure import SecureHeaderssecure_headers = SecureHeaders()def setup_middlewares(app): @app.middleware('response') async def set_secure_headers(request, response): secure_headers.sanic(response)
Setting up middlewares in main.py file.
在main.py文件中设置中间件。
from project.middlewares import setup_middlewares
app = Sanic(__name__)
def init(): ... app.config.from_object(Settings) setup_database() setup_routes(app) setup_middlewares(app) ...
The result is:
结果是:
$ curl -I localhost:8000/booksConnection: keep-aliveKeep-Alive: 5Strict-Transport-Security: max-age=63072000; includeSubdomainsX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffReferrer-Policy: no-referrer, strict-origin-when-cross-originPragma: no-cacheExpires: 0Cache-control: no-cache, no-store, must-revalidate, max-age=0Content-Length: 32Content-Type: text/plain; charset=utf-8
As I promised at the beginning, there is a github repository for each section in this article. Hope this small tutorial helped you to get started with Sanic. There are still many unexplored features in the Sanic framework that you can find and check out in the documentation.
正如我在一开始所承诺的,本文的每个部分都有一个github存储库 。 希望这个小教程可以帮助您开始使用Sanic。 Sanic框架中仍然有许多未开发的功能,您可以在文档中找到并查看。
davitovmasyan/sanic-projectGoin' Fast and asynchronous with Python and Sanic! - davitovmasyan/sanic-projectgithub.com
davitovmasyan / sanic-project Goin'与Python和Sanic快速异步! -davitovmasyan / sanic-project github.com
If you have thoughts on this, be sure to leave a comment.
如果您对此有任何想法,请务必发表评论。
If you found this article helpful, give me some claps ?
如果您觉得这篇文章有帮助,请给我一些鼓掌?
Thanks for reading. Go Fast with Sanic and good luck!!!
谢谢阅读。 Sanic祝您好运,祝您好运!!!
翻译自: https://www.freecodecamp.org/news/goin-fast-and-asynchronous-with-python-and-sanic-387d722f3668/
python sanic