我想在Django服务器启动时执行一些代码,但我希望它只运行一次。目前,当我启动服务器时,它会执行两次。Documentation表示这种情况可能会发生,并且:
您应该在AppConfig类上放置一个标志,以防止重新运行应该只执行一次的代码。
知道如何实现吗?下面的Print语句仍然执行了两次。
from django.apps import AppConfig
import app.mqtt
from apscheduler.schedulers.background import BackgroundScheduler
class MyAppConfig(AppConfig):
name = 'app'
verbose_name = "HomeIoT"
run_already = False
def ready(self):
if MyAppConfig.run_already: return
MyAppConfig.run_already = True
print("Hello")
6条答案
按热度按时间wtlkbnrh1#
使用
python manage.py runserver
时,Django会启动两个进程,一个用于实际的开发服务器,另一个用于在代码更改时重新加载应用程序。您可以在不使用reload选项的情况下启动服务器,并且您将只看到一个进程正在运行:
另请参见the
ready()
method running twice in Django。watbbzwu2#
如果不想使用
--noreload
,可以:替换应用
__init__.py
中用于指定配置的行:通过以下方式:
或者,检查
AppConfig
ready
方法中的RUN_MAIN
环境变量:inb24sb23#
我发现这对我来说很有效没有使用
python manage.py runserver
中的--noreload
标志。检查
ready()
方法中是否存在环境变量。env变量在应用程序结束后不会保留,但如果服务器检测到代码更改,并且在自动重新加载自身后,env变量会保留。83qze16e4#
你需要实现锁。这不是一个简单的问题,当你处理进程和线程时,解决方案会让你感觉不自然。注意,锁的问题有很多答案,一些简单的方法:
文件锁定:确保Linux中的应用程序只有一个示例(请注意,线程默认情况下共享文件锁,因此需要扩展此答案以考虑线程)。
也有这样的答案,它使用了一个名为
tendo
的Python包,该包封装了一个文件锁实现:https://stackoverflow.com/a/1265445/181907Django本身在
django.core.files.locks
中提供了一个抽象的可移植文件锁定实用程序。5ktev3wc5#
正如Roberto提到的,如果您想使用默认的auto_reload功能,那么在通过runserver命令运行服务器时,您需要实现锁定来实现这一点。
Django通过线程实现了auto_reload,因此在两个独立的线程中导入AppConfig,主'command/watch'线程和运行服务器的'reload'线程。在模块中添加一个print语句,您将看到这一操作。'main'线程在BaseCommand执行过程中加载AppConfig文件,'reload'线程在服务器启动时再次加载它们。
如果你的代码不能同时在这两个线程中运行,那么你的选择就受到了一定的限制。你可以实现一个线程锁,这样“reload”线程就不会运行ready();您可以转移到生产环境来运行您的服务器(例如Gunicorn的安装速度非常快,甚至可以用于测试);也可以用其他方法调用方法,而不用ready()。
我建议迁移到适当的环境中,但最佳选择实际上取决于您所调用的方法应该做什么。
6gpjuf906#
发现AppConfig被激发了两次,导致计划程序使用此配置启动了两次。请改为在www.example.com中示例化计划程序urls.py,如下所示: