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

浙公网安备 33010602011771号