英文:
The task in my Django asynchronous view is not executed
问题
Django 异步视图可以立即响应,而任务是异步运行的,但事实上任务无法继续。
async def task_async():
print('任务开始')
await asyncio.sleep(2)
print('任务运行成功')
async def view_async(request):
print('异步开始')
loop = asyncio.get_event_loop()
loop.create_task(task_async())
print('返回')
return HttpResponse("非阻塞的 HTTP 请求")
我期望任务在 HTTP 响应返回后继续运行,但结果是:
异步开始
返回
任务开始
使用 uvicron 是可以的,但是 manage.py 和 daphne project.asgi:application 则不行,这让我感到困惑,uvicron 的结果如下:
异步开始
返回
任务开始
任务运行成功
<details>
<summary>英文:</summary>
Django asynchronous views can respond immediately, while tasks run asynchronously,but in fact the task cannot continue.
async def task_async():
print('task begin')
await asyncio.sleep(2)
print('task run success')
async def view_async(request):
print('async begin')
loop = asyncio.get_event_loop()
loop.create_task(task_async())
print('return')
return HttpResponse("Non-blocking HTTP request")
I expect the task to continue running after the http response returns, but the result is:
async begin
return
task begin
Using uvicron is ok, but manage.py and daphne project.asgi:application are not, this is where i am confused, the result of uvicron ars as follows:
async begin
return
task begin
task run success
</details>
# 答案1
**得分**: 1
默认的 `manage.py runserver` 命令运行一个 [`wsgiref.simple_server`](https://docs.python.org/3/library/wsgiref.html#module-wsgiref.simple_server) 服务器,该服务器从你的 `settings.py` 中提供 `WSGI_APPLICATION`。对于异步视图的调用被包装在 `async_to_sync` 中,在单独的线程中执行,并且没有持久的事件循环。
在开发中要使用 ASGI,需要安装 Daphne 服务器,它带有自己的 `runserver` 命令:
```bash
$ pip install daphne
编辑你的 settings.py
:
INSTALLED_APPS = [
"daphne", # <---
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
...
]
...
ASGI_APPLICATION = "yourproject.asgi.application" # <---
现在,python manage.py runserver
应该表现得像你所期望的那样。
我必须补充的是,Django 中的异步支持主要用于改善 I/O 绑定代码的性能,对于后台任务,更好的做法是使用 Channels、Celery 或其他任务运行器。
英文:
The default manage.py runserver
command runs a wsgiref.simple_server
which serves a WSGI_APPLICATION
from your settings.py
. Calls to async views are wrapped in async_to_sync
, executed in a separate thread and don't have a persistent event loop.
To use ASGI during development, install Daphne server, which comes with its own runserver
command:
$ pip install daphne
Edit your settings.py
:
INSTALLED_APPS = [
"daphne", # <---
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
...
]
...
ASGI_APPLICATION = "yourproject.asgi.application" # <---
Now, python manage.py runserver
should behave like you've expected.
I must add that async support in Django is primarily intended to improve performance for I/O bound code and for background tasks the better practice would be to use Channels, Celery or another task runner.
EDIT: screenshots of both runserver
and standalone daphne
working with the example view from the question:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论