Django后台任务

Posted

技术标签:

【中文标题】Django后台任务【英文标题】:Django Background Task 【发布时间】:2011-09-29 23:21:29 【问题描述】:

我需要在 Django 中每隔几分钟填充一次 SQLite 数据库,但我想提供陈旧的数据,直到数据可用于更新数据库。 (即我不想阻止要收集的数据;我可以阻止的唯一时间是数据库上是否有锁,在此期间我别无选择。)

我也不想安装单独的程序或库。

我将如何设置另一个可以在一堆模型上调用 save() 的线程,而不会遇到线程问题?

【问题讨论】:

“我也不想安装单独的程序或库” 通常是一项昂贵的政策。芹菜为你做这件事。为什么不直接安装 celery? @S.Lott:因为它将在某人的服务器上,我想尽可能避免在服务器上倾倒东西。只是一个单独的线程是不是有点矫枉过正? @S.Lott:我希望它能够工作,但我不明白为什么我需要一个完整的 只是为了创建一个线程。如果你能说服我,我完全赞成,但现在对我来说似乎真的没有必要,特别是因为这是在 Python 中(它似乎包含一个模块,比如,一切)。 @S.Lott: If it was actually simple, you would have done it already. 好吧,我实际上对 Python Django 都是新手,所以我没想到会那么难;我只是觉得我不知道该怎么做。我仍然不确定它的 哪个 部分需要库,但是:它是数据库锁吗?是线程本身吗?或者是其他什么让事情复杂化了,我忘记了? @AHM:非常感谢您提供的信息,尽管我不确定我是否会走那条路。 :) @S.Lott:您的评论就像告诉“n00b”安装 Eclipse 或 Visual Studio,以便他可以制作他的第一个 Hello, World 程序。拥有一个 IDE 可能会有所帮助,但是 (1) 它是多余的,(2) 人们会认为他将总是需要一个 IDE,(3) 他永远不会知道背后的原因建议。所以如果你不是叫我 n00b,而是告诉我为什么我不应该那样做(也许像 AHM 那样?),那么我可能真的明白你的意思。 【参考方案1】:

如果您正在寻找一种轻量级的解决方案,只在后台执行任务,而不是一个成熟的任务管理系统,请查看django-utils。除其他外,它还包括一个 @async 函数装饰器,它将使函数在单独的线程中异步执行。

像这样使用它:

from djutils.decorators import async

@async
def load_data_async():
    # this will be executed in a separate thread
    load_data()

然后您可以调用load_data_async function 来作为后台,或者调用普通的load_data 函数来阻止执行。

请确保安装 2.0 之前的版本,因为它缺少 @async 装饰器。

注意:如果安装 django-utils 太多了,您可以简单地 download it 并在项目中包含几个必需的文件。

【讨论】:

不幸的是,djutils 似乎不再活跃了。至少删除了 readthedocs 和 github 页面。 readthedocs 页面似乎仍然丢失,@Olli,但 the github pages 是可见的。 readthedocs 链接错误:django-utils 文档确实存在 here。 我尝试使用 django-utils 但它似乎与 Django 1.8 不兼容,不是吗? 我也不能用 Django 1.10 做from djutils.decorators import async。它想要导入在 Django 1.6 中已弃用的 hashcompat。我想提交一个错误报告,但该项目似乎已经死了:(【参考方案2】:

快速更新 John Lehmann 的回答:django-background-task 未维护且与较新的 Django 版本不兼容。我们不久前使用新功能对其进行了更新和扩展,并在Github 上维护了新的向后兼容包。可以从 PyPI 下载或安装新的 django-background-tasks 应用程序。

【讨论】:

【参考方案3】:

我有同样的问题,但不想运行像 celery 这样的服务来解决问题。

我在 linux 系统上找到了 posix_spawn。您可以编写在完整的 django 环境中运行的 manage.py 命令。这些命令可以在这个项目的后台执行。

如果在运行过​​程中需要将数据传回网站,我使用memcached。

https://github.com/lukedupin/django_posix_spawn

【讨论】:

【参考方案4】:

取决于您是否需要更新以从读者的角度来看是原子的。如果您不介意同时查看新旧数据,只需创建一个填充数据的custom management command,然后每隔几分钟从cron 运行一次。

如果您需要它看起来原子,通过django.db.transaction 将所有写入包装在一个SQLite transaction 中可能应该为您提供必要的锁。

【讨论】:

我以前从未使用过cron,但是——除非我误解了——这不是一个完全独立的程序吗?这是否意味着我必须创建一个单独的,从我的服务器调用cron,然后运行该程序来更新数据库? cron 是一个在 linux、freebsd 和 osx 上后台运行的进程。请参阅:en.wikipedia.org/wiki/Cron。 @Amar:就像我之前理解的那样,它是一个完全独立的程序……这意味着我需要为更新创建一个新程序。我不确定我是否会走那条路,但是 +1,无论如何感谢你的想法。 @Mehrdad:几乎每个系统都有某种任务调度程序。类 Unix 的有 cron,Windows 有 en.wikipedia.org/wiki/Task_Scheduler【参考方案5】:

Django Background Task 是一个数据库支持的 Django 工作队列,松散地基于 Ruby 的 DelayedJob 库。

你装饰函数来创建任务:

@background(schedule=60)
def notify_user(user_id):
    # lookup user by id and send them a message
    user = User.objects.get(pk=user_id)
    user.email_user('Here is a notification', 'You have been notified')

尽管您仍然需要安排这些任务的东西。一些好处包括自动重试失败的任务,以及为正在运行的任务设置最长持续时间。

这确实涉及另一个依赖项,但可能对一些没有此限制的读者有用。

【讨论】:

【参考方案6】:

Celery.

Celery 是一个基于分布式消息传递的异步任务队列/作业队列。它专注于实时操作,但也支持调度。

Celery 是用 Python 编写的,但协议可以用任何语言实现。它还可以使用 webhook 与其他语言一起运行。

【讨论】:

以上是关于Django后台任务的主要内容,如果未能解决你的问题,请参考以下文章

Django中使用celery完成异步/耗时/后台任务

Django后台任务

如何只运行一次 Django 后台任务

使用 Django 启动和停止定期后台任务

如何在 django 中运行后台任务,完成后,我可以将信息推送到前端。

利用django admin后台配置celery定时任务