Django 非同期View入門
2021/08/18
Ryuji Tsutsui
みんなの
This work is licensed under a Creative Commons Attribution 4.0 International License .
はじめに
自己紹介
-
Ryuji Tsutsui @ryu22e
-
普段は
株式会社hokan でDjangoを 使ってWebサービスを 作っています -
関わっている
コミュニティ: Python Boot Camp、 Shonan.py、 Python Charity Talks in Japanなど -
PyCon APAC 2013、
PyCon JP 2014は スタッフでした -
著書
(共著):『 Python実践レシピ 』
【宣伝】『Python Monthly Topics』公開中!
技術評論社さんの
今日話すこと
-
Webアプリケーションの
非同期処理とは 何か -
Djangoの
非同期Viewとは どんな ものか -
Djangoの
非同期Viewを 書く上での 注意点 -
本番環境で
非同期アプリケーションを 動かすには
1. Webアプリケーションの非同期処理とは何か
非同期処理の説明
非同期処理とは
複数の
非同期処理の説明
非同期処理の
Djangoの
The main benefits are the ability to service hundreds of connections without using Python threads. This allows you to use slow streaming, long-polling, and other exciting response types.
非同期処理の説明
日本語訳:
主な
利点は、 Pythonの スレッドを 使用せずに 数百の 接続を 処理できる ことです。 これに より、 スローストリーミング、 ロングポーリング、 その 他の エキサイティングな レスポンスタイプを 使用する ことができます。
非同期処理の説明
つまり、
PythonのWebアプリケーションで非同期処理を書くには
Webアプリケーションを
WSGIとは
-
Pythonの
世界で よく 使われる 標準インターフェース -
Web Server Gateway Interfaceの
略 -
Djangoでも
サポートしている -
これは
同期処理を 前提と している
ASGIとは
-
WSGIの
「Spiritual successor(精神的続編)」と して 誕生した 標準インターフェース -
Asynchronous Server Gateway Interfaceの
略 -
非同期に
対応している
(ちなみに)「Spiritual successor(精神的続編)」とは
-
ビデオゲームで
よく 使われる 用語で、 前作と 直接関係は ない ものの、 インスピレーションを 得て 作られた 作品の ことを 意味する -
Wikipediaにも
記事が ある: https://en.wikipedia.org/wiki/Spiritual_successor -
例: 『Demon's Souls』→『DARK SOULS』
2. Djangoの非同期Viewとはどんなものか
DjangoでのASGI対応の歴史
DjangoでのASGI対応の歴史
Django 3.0(2019年12月2日リリース)
-
ASGIを
サポートするようになった -
ただし、
非同期Viewが まだ 書けないので 「ASGIを サポートしているのに 非同期アプリケーションは 作れない」と いう 状態
DjangoでのASGI対応の歴史
Django 3.1(2021年3月リリース)
非同期Viewを
import datetime
from django.http import HttpResponse
# 関数の先頭にasyncを入れる
async def current_datetime(request):
now = datetime.datetime.now()
html = 'It is now %s.' % now
return HttpResponse(html)
DjangoでのASGI対応の歴史
Django 4.1(2022年8月3日リリース)
非同期クラスベースViewを
import asyncio
from django.http import HttpResponse
from django.views import View
class AsyncView(View):
# メソッドの先頭にasyncを付ける
async def get(self, request, *args, **kwargs):
await asyncio.sleep(1)
return HttpResponse("非同期ビューのレスポンス")
DjangoでのASGI対応の歴史
(非同期クラスベースViewの
3. Djangoの非同期Viewを書く上での注意点
このコードは実は動かない
from django.http import HttpResponse
from django.views import View
from .models import Book
class AsyncView(View):
async def get(self, request, *args, **kwargs):
titles = []
for book in Book.objects.all():
titles.append(book.title)
return HttpResponse(",".join(titles))
このコードは実は動かない
SynchronousOnlyOperationエラーとは何か
非同期処理の
SynchronousOnlyOperationエラーとは何か
Djangoの
SynchronousOnlyOperationエラーとは何か
前述の
では、どうすればよいか
モデルのasync
を
from django.http import HttpResponse
from django.views import View
from .models import Book
class AsyncView(View):
async def get(self, request, *args, **kwargs):
titles = []
async for book in Book.objects.all():
titles.append(book.title)
return HttpResponse(",".join(titles))
では、どうすればよいか
create()
、
、
などのacreate()
、
、
と
class AsyncView(View):
async def get(self, request, *args, **kwargs):
# メソッドの先頭にaを付ける(awaitを使うのも忘れずに)
book = await Book.objects.acreate(title="Example")
book = await Book.objects.aget(pk=book.pk)
await book.adelete()
...
では、どうすればよいか
モデル以外の
from asgiref.sync import sync_to_async
def sync_only1():
"""同期処理専用の関数"""
...
# sync_to_asyncでラップして実行
await sync_to_async(sync_only1)()
# 関数デコレータとしても使える
@sync_to_async
def sync_only2():
"""同期処理専用の関数"""
...
とりあえず動かしたいならこんな手もある
環境変数 DJANGO_ALLOW_ASYNC_UNSAFE
に
$ # 開発用サーバー実行
$ DJANGO_ALLOW_ASYNC_UNSAFE=1 python manage.py runserver
$ # テスト実行
$ DJANGO_ALLOW_ASYNC_UNSAFE=1 python manage.py test
DJANGO_ALLOW_ASYNC_UNSAFEの使い方について注意
この
DJANGO_ALLOW_ASYNC_UNSAFEの使い方について注意
Djangoには
エラーは
DJANGO_ALLOW_ASYNC_UNSAFEの使い方について注意
SynchronousOnlyOperation
エラーを
Modelの非同期インターフェースについて残念なお知らせ
4.1リリースノート より:
Note that, at this stage, the underlying database operations remain synchronous, with contributions ongoing to push asynchronous support down into the SQL compiler, and integrate asynchronous database drivers.
Modelの非同期インターフェースについて残念なお知らせ
日本語訳:
なお、
現段階では、 基本的な データベース操作は 同期の ままであり、 非同期の サポートを SQLコンパイラに 落とし込み、 非同期データベースドライバを 統合する ための 貢献が 続いています。
Modelの非同期インターフェースについて残念なお知らせ
つまり、
Modelの非同期インターフェースについて残念なお知らせ
おそらく、
本番環境で非同期アプリケーションを動かすには
WSGI用アプリケーションサーバーではダメ
正確には、
ASGI用アプリケーションサーバーを使う
以下の
ASGI用アプリケーションサーバーを使う
(Uvicornを
最後に
まとめ
-
PythonのWebアプリケーションで
非同期処理を 書くには ASGIが 必要 -
Djangoでは
3.0でASGIを サポート、 3.1で 非同期関数ベースView、 4.1で 非同期クラスベースViewを サポート -
非同期View内で
同期処理専用の 処理を 呼ぶと SynchronousOnlyOperation
エラーが発生 -
本番環境で
動かすには ASGI対応アプリケーションサーバーを 使う こと
おしまい
ご
質問あったらどうぞ!