django_apscheduler 定时任务

一. 自动启动定时任务

后端被启动时会自动启动定时任务

1. 目录结构
myproject/
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   └── urls.py
├── app/
│   ├── tasks.py        # 定时任务逻辑
│   └── apps.py         # 启动定时人物的关键
└── manage.py
2. 安装依赖
pip install django-apscheduler
3. 注册
INSTALLED_APPS = [
    """ 其他 """

    "django_apscheduler",
    "aois.apps.AoisConfig",
    # "aois",
]
4. 代码
# /aois/apps.py

from django.apps import AppConfig
from apscheduler.schedulers.background import BackgroundScheduler
import logging
from datetime import datetime
from jianzhuang.utils.loggings import logger

# 任务函数可以放在其他文件中
def my_scheduled_task():
    logger.warning(f"[定时任务] 执行时间: {datetime.now()}")  # 确保日志能输出
    print(f"[定时任务] 执行时间: {datetime.now()}")  # 直接打印到控制台


class AoisConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "aois"

    def ready(self):
        print("===== AoisConfig.ready() 被调用 =====")

        # 1. 初始化调度器(强制启动,跳过 DEBUG 检查)
        scheduler = BackgroundScheduler()

        # 2. 添加任务(每10秒执行一次)
        scheduler.add_job(
            my_scheduled_task,
            "interval",
            seconds=10,
            id="my_task",
            replace_existing=True,
        )

        # 3. 启动调度器
        try:
            scheduler.start()
            print("===== 调度器已启动 =====")
        except Exception as e:
            print(f"===== 调度器启动失败: {e} =====")


>>>>>>>>>>>>>>>>>>>下面是防止任务被多个进程执行多次<<<<<<<<<<<<<<<<<<<<<<<<<<

from django.apps import AppConfig
from apscheduler.schedulers.background import BackgroundScheduler
import socket
from datetime import datetime
from jianzhuang.utils.loggings import logger

def my_scheduled_task():
    """保持原有的时间间隔(如每10秒)"""
    logger.warning(f"[定时任务] 执行时间: {datetime.now()}")
    print(f"[定时任务] 执行时间: {datetime.now()}")

class AoisConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "aois"
    _lock_socket = None  # 跨平台锁

    def ready(self):
        # Windows/Linux通用解决方案
        if not self.acquire_lock():
            print("===== 定时任务已在其他进程中运行 =====")
            return

        print("===== 初始化定时任务 =====")
        scheduler = BackgroundScheduler()
        scheduler.add_job(
            my_scheduled_task,
            "interval",
            seconds=10,  # 保持原时间间隔
            id="my_task",
            replace_existing=True,
        )

        try:
            scheduler.start()
            print("===== 后台任务已启动 =====")
        except Exception as e:
            print(f"===== 后台任务启动失败: {e} =====")

    def acquire_lock(self):
        """跨平台进程锁(Windows/Linux通用)"""
        try:
            # 使用UDP端口锁(比文件锁更可靠)
            self._lock_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self._lock_socket.bind(('127.0.0.1', 47200))  # 47200是任意空闲端口
            return True
        except (socket.error, OSError):
            return False


二. 手动启动定时任务

1. 目录结构

需要手动执行命令 见 5

本质就是django自定义命令, app/management/commands/bgtask.py 文件名是啥 python manage.py <文件名>
myproject/
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   └── urls.py
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── views.py
│   ├── management/
│   │   ├── __init__.py
│   │   ├── commands/
│   │   │   ├── __init__.py
│   │   │   ├── tasks.py      # 存放任务的地方
│   │   │   └── bgtask.py

└── manage.py
2. 安装依赖
pip install django-apscheduler
3. 注册
INSTALLED_APPS = [
    """ 其他 """

    "django_apscheduler",
    "aois",
]
4. 代码
# bgtask.py

from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.schedulers.blocking import BlockingScheduler
from django.core.management.base import BaseCommand
from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore

from ._test import my_scheduled_task
from project import settings


class Command(BaseCommand):
    help = '启动后台定时任务'

    def handle(self, *args, **options):

        # 调度器的初始设置
        scheduler = BlockingScheduler(timezone=settings.TIME_ZONE)  # 当前线程不会执行其他任务,
        scheduler.add_jobstore(DjangoJobStore())  # 使用 Django 的数据库模型来存储任务信息
        scheduler.add_executor(ThreadPoolExecutor(max_workers=8))  # 表示线程池的最大工作线程数为 8

        scheduler = BackgroundScheduler()

        # 2. 添加任务(每10秒执行一次)
        scheduler.add_job(
            my_scheduled_task,
            "interval",
            seconds=10,
            id="my_task",
            replace_existing=True,
        )

        try:
            scheduler.start()
            self.stdout.write(self.style.SUCCESS('后台任务已启动'))
        except KeyboardInterrupt:
            scheduler.shutdown()
            self.stdout.write(self.style.SUCCESS('后台任务已停止'))

# tasks.py

from datetime import datetime
from project.utils.loggings import logger

def my_scheduled_task():
    logger.info(f"[定时任务] 执行时间: {datetime.now()}")
    print(f"[定时任务] 执行时间: {datetime.now()}")
    # 在这里写你的任务逻辑
5. 启动
python manage.py bgtask
posted @ 2025-05-30 12:56  codegjj  阅读(139)  评论(0)    收藏  举报