Python中Django启动时如何启动一个新线程
需求:Django 在启动时初始化一个子线程,用于在后台轮训心跳任务
心跳任务,监控其他节点
目前测试情况:
1.定时器( apscheduler )的方案,并不是我想要的。比如 任务可能随着节点增多,本来 5 秒能处理完的 job,变成 10 秒。apscheduler 做不到顺延执行同 job (我是没找到办法)
2.尝试过 在 view 中创建线程,加载的代码没问题,但是创建线程无效果没 log。猜测 manage.py runserver 的时候是 fork 了子进程。
- manage.py 中创建线程,会阻塞主进程。
那位大佬 来指点一下。小弟感谢不尽(抱拳)
Python中Django启动时如何启动一个新线程
用芹菜队列应该可以
在Django启动时启动新线程,通常是在ready()方法里用threading.Thread来实现。下面是一个完整的示例,演示如何在应用加载时启动一个后台线程。
首先,在你的Django应用(比如叫myapp)的apps.py文件中,重写AppConfig类的ready()方法:
# myapp/apps.py
import threading
import time
from django.apps import AppConfig
class MyAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
# 确保只在主线程中运行一次,避免在开发服务器重载时重复启动
import sys
if 'runserver' in sys.argv or 'gunicorn' in sys.argv: # 根据你的部署方式调整
self.start_background_thread()
def start_background_thread(self):
def background_task():
while True:
# 这里是你的后台任务逻辑
print("后台线程正在运行...")
time.sleep(10) # 每10秒执行一次
# 创建并启动线程,设置为守护线程,这样主进程退出时它会自动结束
thread = threading.Thread(target=background_task, daemon=True)
thread.start()
print("后台线程已启动")
然后,在settings.py中,确保你的应用使用这个自定义的AppConfig:
# settings.py
INSTALLED_APPS = [
# ...
'myapp.apps.MyAppConfig', # 替换为你的AppConfig路径
# ...
]
关键点说明:
ready()方法会在Django应用完全加载后执行,是启动后台任务的合适位置。- 使用
daemon=True将线程设为守护线程,避免阻止Django正常关闭。 - 通过检查
sys.argv来限制只在运行服务器时启动线程,防止在migrate等管理命令中意外运行。
一句话总结: 在AppConfig的ready方法里用threading.Thread启动守护线程就行。
创建线程怎么会阻塞主线程呢?能贴下代码么?
我用 tornado 也可以创建线程啊<br> # 创建队列处理线程<br> threading.Thread(target=handle_queue, name="handle_queue").start()<br> # 启动 tornado<br> port = os.environ.get('PORT', 8888)<br> api.listen(port)<br> print('listen on {}'.format(port))<br> tornado.ioloop.IOLoop.current().start()<br>
创建线程的操作在哪都不会阻塞主线程吧,是不是你 join 了。。
好多业务通过 celery 就能做到,但是你问的是如何开线程,把创建线程的代码放在 app 的 init.py 中即可,并保证 app 会被 import
"apscheduler 做不到顺延执行同 job"是什么意思?” misfire_grace_time “参数是你要的吗?
Django crontab
首先,你这个解决方案并不恰当,用 supervisor 启动独立守护进程更加合适,不过你的方案要实现也并非不可能。
django 程序一般会被托管给 WSGI 容器来运行,你在 django 程序中无法预料会是以多进程或是多线程运行,你需要一个全局互斥对象( Mutex )来保证这个线程只被运行一次,可以通过文件锁来实现
可能说的比较乱。
我只是想 创建 django 启动时加载一个子线程
试过加载 init 中,通过 manage.py 启动项目 会阻塞 启动。(子线程创建没问题,但是子线程里是死循环,来处理业务)
wsgi 架构里 线程是 anti pattern。建议放弃治疗。
首先你要使用 BackgroundScheduler,然后在你 app 下的 apps.py 中的 AppConfig 子类添加 ready 方法,该方法每次应用载入前被启动一次,然后在 INSTALLED_APPS 注册该类名,而不是 app 名。
我只是想 创建 django 启动时加载一个子线程 ,不需要 apscheduler
触发器每 5 秒执行,但是任务 实际耗时 10 秒。顺延执行,上个耗时 10 秒任务完成后的 5 秒 触发
django.channles,可以试试,有延时其中任务这个功能,你可以创建一个 5 秒的延时任务,但时间之后,执行任务 ,执行完毕,在去掉创建延时任务的接口。
django 创建子线程确实会阻塞的,应该是 python 全局锁


