- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我只是将一个旧项目升级到 Python 3.6,并发现有这些很酷的新 async/await 关键字。
我的项目包含一个网络爬虫,目前性能不是很好,大约需要 7 分钟才能完成。
现在,由于我已经安装了 django restframework 来访问我的 django 应用程序的数据,我认为拥有一个 REST 端点会很好,我可以通过一个简单的 POST 请求从远程启动爬虫。
但是,我不希望客户端同步等待爬虫完成。我只想直接给他发爬虫已经启动的消息,在后台启动爬虫。
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.conf import settings
from mycrawler import tasks
async def update_all_async(deep_crawl=True, season=settings.CURRENT_SEASON, log_to_db=True):
await tasks.update_all(deep_crawl, season, log_to_db)
@api_view(['POST', 'GET'])
def start(request):
"""
Start crawling.
"""
if request.method == 'POST':
print("Crawler: start {}".format(request))
deep = request.data.get('deep', False)
season = request.data.get('season', settings.CURRENT_SEASON)
# this should be called async
update_all_async(season=season, deep_crawl=deep)
return Response({"Success": {"crawl finished"}}, status=status.HTTP_200_OK)
else:
return Response ({"description": "Start the crawler by calling this enpoint via post.", "allowed_parameters": {
"deep": "boolean",
"season": "number"
}}, status.HTTP_200_OK)
import threading
@api_view(['POST', 'GET'])
def start(request):
...
t = threading.Thread(target=tasks.update_all, args=(deep, season))
t.start()
...
最佳答案
这在 Django 3.1+ 中是可能的,在 introducing asynchronous support 之后.
关于异步运行循环,你可以通过 uvicorn
运行 Django 来使用它。或任何其他 ASGI 服务器而不是 gunicorn
或其他 WSGI 服务器。
不同之处在于,在使用 ASGI 服务器时,已经有一个运行循环,而在使用 WSGI 时需要创建一个。使用ASGI,您可以简单地定义async
直接在 views.py
下的功能或其 View 类的继承函数。
假设您使用 ASGI,您有多种方法可以实现这一点,我将描述一些(例如其他选项可以使用 asyncio.Queue
):
start()
异步 start()
async,您可以直接使用现有的运行循环,并通过使用
asyncio.Task
,您可以触发并忘记进入现有的运行循环。如果你想开火但记住,你可以创建另一个
Task
跟进这一点,即:
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.conf import settings
from mycrawler import tasks
import asyncio
async def update_all_async(deep_crawl=True, season=settings.CURRENT_SEASON, log_to_db=True):
await tasks.update_all(deep_crawl, season, log_to_db)
async def follow_up_task(task: asyncio.Task):
await asyncio.sleep(5) # Or any other reasonable number, or a finite loop...
if task.done():
print('update_all task completed: {}'.format(task.result()))
else:
print('task not completed after 5 seconds, aborting')
task.cancel()
@api_view(['POST', 'GET'])
async def start(request):
"""
Start crawling.
"""
if request.method == 'POST':
print("Crawler: start {}".format(request))
deep = request.data.get('deep', False)
season = request.data.get('season', settings.CURRENT_SEASON)
# Once the task is created, it will begin running in parallel
loop = asyncio.get_running_loop()
task = loop.create_task(update_all_async(season=season, deep_crawl=deep))
# Fire up a task to track previous down
loop.create_task(follow_up_task(task))
return Response({"Success": {"crawl finished"}}, status=status.HTTP_200_OK)
else:
return Response ({"description": "Start the crawler by calling this enpoint via post.", "allowed_parameters": {
"deep": "boolean",
"season": "number"
}}, status.HTTP_200_OK)
async
首先将请求路由到的函数,
as it happens with DRF (截至今日)。
async
adapter functions ,但请注意,从同步上下文切换到异步上下文,反之亦然,随
a small performance penalty 一起提供。大约 1ms。请注意,这一次,运行循环收集在
update_all_sync
中。函数代替:
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.conf import settings
from mycrawler import tasks
import asyncio
from asgiref.sync import async_to_sync
@async_to_sync
async def update_all_async(deep_crawl=True, season=settings.CURRENT_SEASON, log_to_db=True):
#We can use the running loop here in this use case
loop = asyncio.get_running_loop()
task = loop.create_task(tasks.update_all(deep_crawl, season, log_to_db))
loop.create_task(follow_up_task(task))
async def follow_up_task(task: asyncio.Task):
await asyncio.sleep(5) # Or any other reasonable number, or a finite loop...
if task.done():
print('update_all task completed: {}'.format(task.result()))
else:
print('task not completed after 5 seconds, aborting')
task.cancel()
@api_view(['POST', 'GET'])
def start(request):
"""
Start crawling.
"""
if request.method == 'POST':
print("Crawler: start {}".format(request))
deep = request.data.get('deep', False)
season = request.data.get('season', settings.CURRENT_SEASON)
# Make update all "sync"
sync_update_all_sync = async_to_sync(update_all_async)
sync_update_all_sync(season=season, deep_crawl=deep)
return Response({"Success": {"crawl finished"}}, status=status.HTTP_200_OK)
else:
return Response ({"description": "Start the crawler by calling this enpoint via post.", "allowed_parameters": {
"deep": "boolean",
"season": "number"
}}, status.HTTP_200_OK)
在这两种情况下,该函数都会快速返回 200,但从技术上讲,第二个选项更慢。
IMPORTANT: When using Django, it is common to have DB operations involved in these async operations. DB operations in Django can only be synchronous, at least for now, so you will have to consider this in asynchronous contexts.
sync_to_async()
becomes very handy for these cases.
关于django - 在 Django restframework 中使用 python async/await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46820009/
一 前言 经过权限判断之后就是进行频率的判断了,而频率的判断和权限又不一样,认证、权限和频率的执行流程都差不多,使用配置里面的相关类来进行判断。而不和认证和权限一样,频率的配置没有,
前言 最近学习了 django 的一个 restframework 框架,对于里面的执行流程产生了兴趣,经过昨天一晚上初步搞清楚了执行流程(部分方法还不太清楚),于是想详细的总结一下当来一个请求时
系统:ubuntu18.04 x64 GitHub:https://github.com/xingjidemimi/DjangoAPI.git 安装 ?
我想为我的用户使用用户名或电子邮件和密码进行一些自定义身份验证。在第一次使用电子邮件和密码登录时,api 应该返回相应的用户 token 。对于 api 的所有其他操作,我需要使用 token ,这是
我有一个常规的 django 站点,djangorestframework (v2.3.14) 在“/api”下提供 restful api。在本地机器上一切正常(mac/mavericks),在远程
我正在使用Django Restframework 3.3.3,并且尝试使用通用 View ,但是我希望覆盖序列化程序验证错误消息。我得到以下代码,当没有给出名称字段时,出现“名称字段不能为空”的代码
我正在使用 python 2.7 和 django 1.7 构建 API,但我遇到了问题。我不是 Rest Framework 方面的专家,但我了解基 native 制。 我可以通过举个例子来继续我的
我的问题与 django-rest-framework 有关,是关于如何对元素进行分组的。 这是我的serializers.py from collaborativeAPP.models import
我正在使用Django restframework和 Elasticsearch 来开发移动应用程序的后端应用程序。我需要开发一个时间轴API,以加载该用户正在关注的其他用户的帖子时间轴。以及他们关注
我使用路由器创建 url,现在我想为我的 api 创建 url,但问题是,我收到错误 createuser() missing 1 required positional argument: 'req
我有两个模型,分别是问题和与该问题一致的选择集。我想结合这两个模型来创建一个 API,它显示问题列表及其选择。 这些是我的模型: class Question(models.Model): q
我目前正在使用线程标题中提到的技术进行一个项目。 我在浏览器上运行了这一切(该应用程序托管在 heroku 上),但是当我尝试从我的 Ionic 2 应用程序连接到 websockets 时,我总是在
我正在使用 Django rest framework-JWT 进行身份验证来处理 protected url,我正在尝试使用 IsAutchinted 保护 UserDetail View 。来自r
我只是将一个旧项目升级到 Python 3.6,并发现有这些很酷的新 async/await 关键字。 我的项目包含一个网络爬虫,目前性能不是很好,大约需要 7 分钟才能完成。 现在,由于我已经安装了
j查询: $.ajax({ url: '/notify/', type:'GET', dataType: 'json',
我正在使用 django restframework 并希望处理多个数据库。我正在使用 django 函数 using(alias) 和 switch_db(alias) 在我想要获取、发布或更新数据
在 django RestFramework 中,是否有任何“官方”方式来生成“Api Root”的文档? 在查看了 RestFramework 的源代码后,我通过继承 DefaultRouter 找
我是 Multi-Tenancy 架构的新手,正在使用 django-tenant-schema 开发 SaaS 产品 我的要求是客户注册产品。对于每个注册的客户,我都通过遵循单一数据库和隔离模式方法
我试图找出是否可以使用 Django Rest 框架中的通用 api 方法在同一 View 中发布和修补。我不认为有任何通用类允许完全创建和更新,任何人都可以告诉我下面的配置是否允许我在同一 View
您好,我尝试添加到我的项目 swagger 但它返回 401 错误,请帮助我解决这个问题 这是我的路由器 from . import router schema_view = get_sche
我是一名优秀的程序员,十分优秀!