【问题标题】:How to use python multiprocessing module in django view如何在 django 视图中使用 python 多处理模块
【发布时间】:2016-02-29 21:17:37
【问题描述】:

我有一个简单的函数来遍历 URL 列表,使用 GET 检索一些信息并相应地更新数据库 (PostgresSQL)。该功能完美运行。但是,一次一个地浏览每个 URL 会占用太多时间。

使用 python,我可以执行以下操作来并行执行这些任务:

from multiprocessing import Pool

def updateDB(ip):
     code goes here...

if __name__ == '__main__':
    pool = Pool(processes=4)              # process per core
    pool.map(updateDB, ip)

这工作得很好。但是,我试图找到如何在 django 项目上做同样的事情。目前我有一个函数(视图)可以遍历每个 URL 以获取信息并更新数据库。

我唯一能找到的就是使用 Celery,但这对于我想要执行的简单任务来说似乎有点过于强大了。

有什么简单的我可以做或者我必须使用 Celery 吗?

【问题讨论】:

  • 这是一个重复的任务吗?也许作为 cronjob 运行的自定义管理命令是另一种选择。
  • 这真的取决于你想要的响应时间。您可以让服务器在生成 Celery 任务后立即响应,或者您可以进行多处理,然后仍然需要一些时间。不过不要打扰multiprocessing,我建议使用优秀的joblib 库。

标签: python django multiprocessing


【解决方案1】:

目前我有一个函数(视图)可以遍历每个 URL 以获取 信息,并更新数据库。

这意味着响应时间对您来说并不重要,而不是在后台(异步)执行,如果您的响应时间减少 4(使用 4 个子进程/线程),您可以在前台执行.如果是这种情况,您可以简单地将示例代码放在您的视图中。喜欢

from multiprocessing import Pool

def updateDB(ip):
     code goes here...

def my_view(request):
    pool = Pool(processes=4)              # process per core
    pool.map(updateDB, ip)
    return HttpResponse("SUCCESS")

但是,如果您想在后台异步执行此操作,那么您应该使用 Celery 或遵循@BasicWolf 的建议之一。

【讨论】:

  • 这正是我的情况。我不需要在后台运行任何东西(这就是为什么我发现 Celery 不是最好的解决方案)。我实际上尝试了您的建议,因为我认为它可能有效。但是,我收到一个错误“尚未加载模型”。虽然这是不可能的。您知道为什么会出现以下异常吗?异常类型:AppRegistryNotReady 异常值:模型尚未加载。
  • 你的 Django 版本是什么?在 Django 1.8.2 上为我工作
  • Django 版本 1.8.6 我将再次检查我的代码以确保我正确地进行了所有更改。我想我会用一个新的简单功能来试试这个。也许我的代码中的其他东西会造成麻烦。
  • 它基本上可以工作。我的例外是在“updateDB”函数的某个地方,我将类添加到类(ManyToMany 关系):cluster.clusterRpas.add(rpa)。由于某种原因,出现了“尚未加载模型”的异常。
  • 如果创建具有强大异步支持的微服务(如 FastAPI)并将其用于异步调用 Django API (这将为一个用例完成任务)可能是一种解决方案,您怎么看?
【解决方案2】:

虽然使用 Celery 可能看起来有点过头了,但它是一种众所周知的异步任务方式。本质上,Django 服务于 WSGI 请求-响应循环,它对多处理或后台任务一无所知。

以下是替代选项:

【讨论】:

  • 我很好奇为什么你认为 Celery 是矫枉过正的?似乎 Go To 解决方案适用于依赖农业工作并保持网页更新进度的生产站点。也许很难安装和运行?当然,这似乎有点牵涉其中,Redis 队列以较低的准入门槛自我推销。
  • 这真的取决于一个案例。如果基础设施仅限于“仅限 Django + Python”,并且无法使用像 RabbitMQ 这样的消息代理,那么将会遇到困难。但可以肯定的是,对于比小型爱好项目更严肃的事情,我会选择 Celery。
  • 使用 celery 是否可以等到所有函数调用都被执行?喜欢asyncio.gather
【解决方案3】:

我会推荐使用gevent 进行多线程解决方案而不是多处理。在限制生成新进程的生产环境中,多处理可能会导致问题。

示例代码:

from django.shortcuts import HttpResponse
from gevent.pool import Pool

def square(number):
    return number * number

def home(request):
    pool = Pool(50)
    numbers = [1, 3, 5]
    results = pool.map(square, numbers)
    return HttpResponse(results)

【讨论】:

  • Gevent 适用于协程感知的 I/O 绑定任务。完成这项任务的工具完全不正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 2017-12-11
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
相关资源
最近更新 更多