我正在尝试研究如何在Django中的后台线程中运行进程。我是Django和线程的新手,所以如果我使用的术语错了,请耐心等待。
这是我的代码。基本上我希望start_processing
一旦触发success
函数就开始start_processing
。但是start_processing
是一种很容易花费几分钟或失败的功能(它取决于我无法控制的外部服务),我不希望用户必须等待它在呈现视图之前成功完成。 (就他们而言,“成功”并不取决于def success(request, filepath):
start_processing(filepath)
return render_to_response('success.html', context_instance = RequestContext(request))
的结果;如果失败,我是唯一需要担心的人。)
start_processing
从谷歌搜索结果来看,大多数人都认为Django中没有使用后台线程,而cron作业更适合。但是我希望{{1}}一旦用户进入成功函数就开始,而不是等到cron作业运行。有没有办法做到这一点?
答案 0 :(得分:20)
如果您真的需要快速入侵,只需使用subprocess启动流程。
但我不建议产生一个流程(甚至一个线程),特别是如果您的网站是公开的:在高负载的情况下(可能是“自然的”或者是您将会产生许多进程或线程,最终会耗尽所有系统资源并终止您的服务器。
我建议使用作业服务器:我使用DoS(Celery作为后端),它非常简单,效果很好。您可以查看许多其他作业服务器,例如RabbitMQ或Gearman。在您的情况下,作业服务器可能有点过分:您可以简单地运行Redis并将其用作轻量级消息服务器。以下是Redis如何执行此操作。
干杯
答案 1 :(得分:9)
如果有人真的想要运行另一个线程
def background_process():
import time
print("process started")
time.sleep(100)
print("process finished")
def index(request):
import threading
t = threading.Thread(target=background_process, args=(), kwargs={})
t.setDaemon(True)
t.start()
return HttpResponse("main thread content")
这将首先返回响应,然后将“process finished”打印到控制台。因此用户不会遇到任何延迟。
使用Celery绝对是一个更好的解决方案。但是,对于服务器等有限的非常小的项目,安装Celery可能是不必要的。
您可能还需要在大型项目中使用线程。因为在所有服务器上运行Celery并不是一个好主意。然后,将无法在每个服务器中运行单独的进程。您可能需要线程来处理这种情况。文件系统操作可能是一个例子。虽然这种情况不太可能,但使用长期运行的Celery仍然会更好。
明智地使用。
答案 2 :(得分:5)
我不确定你需要一个线程。听起来你只想生成一个进程,所以请查看subprocess
模块。
答案 3 :(得分:3)
IIUC,这里的问题是网络服务器进程可能不喜欢额外长时间运行的线程,它可能会随着需求上升和下降等原因而杀死/生成服务器进程等。
通过与外部服务流程进行此类处理的沟通,您可能会更好,而不是将其嵌入到Web服务器的wsgi / fastcgi流程中。
如果您发送的唯一内容是文件路径,那么编写该服务应用程序应该非常容易。