python - Django 通过 REST 步骤或处理消息
问题描述
出于学习目的,我想实现下一件事:
例如,我有一个在后台运行 selenium 的脚本,并且我有一些日志消息可以帮助我查看终端中发生了什么。但我想在对 Angular 应用程序的 REST 请求中获得相同的消息。
print('Started')
print('Logged in')
...
print('Processing')
...
print('Success')
在我的 view.py 文件中
class RunTask(viewsets.ViewSet):
queryset = Task.objects.all()
@action(detail=False, methods=['GET'], name='Run Test Script')
def run(self, request, *args, **kwargs):
task = task()
if valid['success']:
return Response(data=task)
else:
return Response(data=task['message'])
def task()
print('Staring')
print('Logged in')
...
print('Processing')
...
print('Success')
return {
'success': True/False,
'message': 'my status message'
}
现在它只显示任务的结果。但我想获得相同的消息来指示前端的进程状态。我无法理解如何组织它。
或者我如何从角度了解我的进程状态?
解决方案
不幸的是,事情并没有那么简单。事实上,REST API 允许您启动任务,但由于它在同一个线程中运行,HTTP 请求将阻塞,直到任务完成后再发送响应。您的print
语句不会出现在 HTTP 响应中,而是出现在您的服务器输出中(如果您查看运行的 shell python manage.py runserver
,您会看到这些print
语句)。
现在,如果您希望实时获得这些输出,则必须寻找 WebSockets。它们允许您在浏览器和服务器之间打开一条“隧道”,并实时发送/接收消息。django-channels 库允许您实现它们。
但是,对于长时间运行的后台任务(如 Selenium 刮刀),我建议查看Celery 任务队列。基本上,您的 Django 进程会将任务安排到队列中。然后,队列中的任务将由一个(或多个!)“工作”进程执行。这样做的好处是您的 Django 进程不会被长任务阻塞:它只是将一些工作添加到队列中然后响应。
当您在队列中添加任务时,Celery 将为您提供此任务的唯一标识符,您可以在 HTTP 响应中返回该标识符。然后,您可以很好地实现另一个端点,该端点在参数中接受任务 id 并返回任务的状态(它是挂起的?完成的?失败的?)。
为此,您必须设置一个“代理”,这是一种存储要执行的任务及其结果的数据库(通常是 RabbitMQ 或 Redis)。芹菜文档很好地解释了这一点:https ://docs.celeryproject.org/en/latest/getting-started/brokers/index.html
无论您选择哪种方式,这都不是一件微不足道的事情,并且需要相当多的工作才能获得一些结果;但有趣的是它如何扩展了经典 HTTP 服务器的可能性。
推荐阅读
- python - [更新]Google 搜索 Python 模块
- r - R:使用 dir() 函数提取文件,并在矩阵中识别模式
- android - 即使在终止应用程序后仍运行的 Android 服务
- python - python比较两个列表并保留第二个列表索引
- python - 用于 python 的 Azure 函数无法访问
- jmeter - Apache-JMeter 5.4
- sql - 如何使用sql提取具有重叠时间的行
- vue.js - 在 vuejs 中“安装”之前获取子 DOM 元素高度
- mongodb - 编写一个 Bash shell 脚本来读取 mongodb 日志文件并将其内容写入另一个文本文件
- c# - 如何断言 API 响应具有特定结构?