python - 我正在尝试从 Django 内运行一个无尽的工作线程(守护进程)

标签 python django multithreading infinite-loop indefinite

我有一个工作线程,其唯一任务是每 10 分钟从数据库中查询一次事件用户列表,并在满足特定条件时向他们发送短信(每分钟检查一次);而且工作线程根本不会妨碍主应用程序。

到目前为止,我设法让线程启动并运行,并且发送短信也可以正常工作。然而,由于某些原因,线程在一段随机时间(小时)后停止/被杀死。我在一段时间内运行 try: except Exception as e: True 来捕获发生的错误。此外,我打印出一条消息,说明发生了什么错误。

嗯,我从来没有看到任何消息,线程肯定已关闭。因此,我怀疑 Gunicorn 或 Django 会优雅地终止我的线程。

我已经在代码中放置了日志和打印语句,但没有找到任何表明我的线程被杀死的原因。

我的 wsgi.py 函数,我在其中调用该函数来启动我的线程

"""
WSGI config for django_web project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_web.settings')

application = get_wsgi_application()

'''
Start background services
Import has to happen after "get_wsgi_application()"; otherwise docker container crashes
'''
try:
    from threading import Thread
    from timesheet.admin import runWorkmateServices

    runWorkmateServices()

except Exception as exp:
    print(exp)

从 wsgi.py 中调用的函数。我仔细检查线程是否已启动,以避免两个线程启动并运行。

def runWorkmateServices(request=None):
    service_name = 'TimeKeeperWorkMateReminderService'

    thread_found = False
    for thread in threading.enumerate():
        if service_name in thread.name:
            thread_found = True
            break  # Leave loop now

    if thread_found:
        print(f'Service has already been started: {service_name}')
        if request:
            messages.add_message(request, messages.ERROR, f'Service has already been started:: {service_name}')
    else:
        Thread(target=WorkMateReminders, args=(), name=service_name, daemon=True).start()
        print(f'Started Service: {service_name}')
        if request:
            messages.add_message(request, messages.SUCCESS, f'Started Service: {service_name}')

工作线程本身

def WorkMateReminders():
    print('Thread Started: WorkMateReminders')
    timer = 0
    employees = User.objects.none()

    while True:

        try:
            # Update user list every n * sleep time (10 minutes)
            if timer % 10 == 0:
                timer = 0
                # Get active employees
                employees = User.objects.filter(is_active=True, profile__workmate_sms_reminders_activated=True)
                print(f'Employees updated at {datetime.now().date()} - {datetime.now().time()}: {employees}')

            WorkMateCheckClockOffTimes(employees=employees)

            WorkMateClockOnReminder(employees=employees)

            WorkMateEndOfBreakReminder(employees=employees)

            timer += 1  # increment timer

        except Exception as exp:
            print(f'Error: {exp}')

        time.sleep(60 * 1)

我的目标是只要 Django 启动就让这个工作线程运行。

最佳答案

大多数 WSGI 服务器会定期生成被杀死/回收的工作线程,从这些工作线程生成线程并不是解决问题的最佳方案。有几种方法可以解决这个问题

定时任务

Create a management command这就是你想要的并配置 cron每 10 分钟运行一次

celery /Celerybeat

设置celery worker,这是一个与 Django 应用程序异步运行的进程,并使用 celerybeat您可以定期运行任务

关于python - 我正在尝试从 Django 内运行一个无尽的工作线程(守护进程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56943333/

相关文章:

python - pandas 使用 float64 的最大小数位数

python - 有没有办法使用 Pycuda 检索特定值的索引?

python - 在Python模块中调用C头文件函数

python / celery : how can I kill subtasks when killing a parent task?

c# - 哪个异步调用用于数据库连接和仍然响应的 GUI?--

python - 如果一次读取整个文件需要 with 语句?

django - 高效删除 Django 中孤立的 m2m 对象/标签

C++: 跨线程异常处理问题与 boost::exception

Python线程运行()阻塞

django - django独特领域