如何从 Django 发送异步 HTTP 请求并在 python2.7 中等待结果?

Posted

技术标签:

【中文标题】如何从 Django 发送异步 HTTP 请求并在 python2.7 中等待结果?【英文标题】:How to send asynchronous HTTP requests from Django and wait for results in python2.7? 【发布时间】:2019-07-05 00:47:44 【问题描述】:

我有几个 API 作为数据源,例如 - 博客文章。我想要实现的是从 Django 视图并行向这个 API 发送请求并获得结果。无需将结果存储在数据库中,我需要将它们传递给我的视图响应。我的项目是在 python 2.7 上编写的,所以我不能使用 asyncio。我正在寻找有关解决它的最佳实践的建议(芹菜,龙卷风,其他什么?)以及如何实现这一目标的示例,因为我只是以异步方式开始我的方式。谢谢。

【问题讨论】:

考虑到对 python 2.7 的支持将在大约 11 个月后结束,您是否考虑过更新项目以使用 python 3? 我很乐意,但如果现在可以,我不会问这个问题。 【参考方案1】:

我从futures lib 找到了使用 concurrent.futures ThreadPoolExecutor 的解决方案。

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = executor.submit(load_url, url, 60): url for url in URLS
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

您也可以查看rest of the concurrent.futures doc。

重要! ProcessPoolExecutor 类在 Python 2 上存在已知(无法修复的)问题,因此不应依赖于关键任务工作。

【讨论】:

【参考方案2】:

一种解决方案是使用 Celery 并将您的请求参数传递给它,然后在前面使用 AJAX。

例子:

def my_def (request):
    do_something_in_celery.delay()
    return Response(something)    

要控制 Celery 中的任务是否完成,可以将 Celery 的返回值放在一个变量中:

task_run = do_something_in_celery.delay()

在 task_run 中有一个属性 .id。 这个.id你回到你的前面,用它来监控任务的状态。

并且你在 Celery 中执行的函数必须有 de decorator @task

@task
do_something_in_celery(*args, **kwargs):

您将需要控制任务,例如 Redis 或 RabbitMQ。

看看这个网址:

http://masnun.com/2014/08/02/django-celery-easy-async-task-processing.html

https://buildwithdjango.com/blog/post/celery-progress-bars/

http://docs.celeryproject.org/en/latest/index.html

【讨论】:

保罗,谢谢分享。但主要目标是避免额外的 AJAX 请求。有什么想法吗? 不,我不知道没有 AJAX 怎么办。对不起!

以上是关于如何从 Django 发送异步 HTTP 请求并在 python2.7 中等待结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中异步发送 API 请求过程?

React + Django 在 HTTP 请求中发送原始密码,安全性讨论

如何从 django 视图发送 json 并在 HTML 上接收它

在加载表单之前等待异步函数(Http 请求)

使用脚本从客户端发送 http post 并在 NODEJS 中获取请求

发送多个同时请求时,单线程异步系统中野兽增强异步 http 客户端的行为