TL; DR:
У меня есть приложение, в котором я хочу запускать процедуру каждый день в полночь (для этого я использую APScheduler). В середине этой процедуры предполагается получить доступ к данным нескольких моделей Django.
Логика:
Django работает> запустить apps.py> запустить scheduler.py> запустить рутину.py> получить доступ к models.py.
Исключения приведены в нижней части поста.
- Вот подробности:
Мой каталог такой:
myproject/
- manage.py
+ myproject/
-- settings.py
-- wsgi.py
-- ...
+ myapp/
-+ static/
-+ templates/
-- admin.py
-- apps.py
-- models.py
-- views.py
-- scheduler.py #<<<<<<<<<<
-- routine.py #<<<<<<<<<<
-- ...
myapp / models.py
class MyModel(models.Model):
field1 = models.DateField(auto_now=True)
field2 = models.DecimalField(max_digits=19, decimal_places=16)
...
myapp / apps.py
from django.apps import AppConfig
from .scheduler import ScheduledRoutine
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
routine = ScheduledRoutine()
routine.start()
myapp / scheduler.py
from .routine import MyRoutine
#from ..routine import MyRoutine # See error nr3 <<<<<<<<<
from apscheduler.schedulers.background import BackgroundScheduler
class ScheduledRoutine(object):
def start(self):
self.scheduler = BackgroundScheduler()
startdate = datetime.now() #For brevity assume datetime object
self.scheduler.add_job(self.routine, 'interval', days=1, start_date=startdate)
self.scheduler.start()
def routine(self):
data = MyRoutine()
myapp / рутинный.py
import os
os.environ["DJANGO_SETTINGS_MODULE"] = "myproject.settings"
import django
django.setup()
from .models import MyModel
#from myapp.models import MyModel # See error nr3 <<<<<<<<<
class MyRoutine(object):
def __init__(self, arg):
self.arg = arg
data = MyModel.objects.filter(reliable=True)
self.do_something(data)
- Исключения и что не работает
Я уже пробовал несколько вещей, это те, которые япомните:
- Ошибка Nr1:
При текущем состоянии вещей (как показано выше) это ошибка:
Watching for file changes with StatReloader
Exception in thread django-main-thread:
Traceback (most recent call last):
File "C:\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
self.run()
File "C:\Python\Python37\lib\threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "C:\venv\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
fn(*args, **kwargs)
File "C:\venv\lib\site-packages\django\core\management\commands\runserver.py", line 109, in inner_run
autoreload.raise_last_exception()
File "C:\venv\lib\site-packages\django\utils\autoreload.py", line 77, in raise_last_exception
raise _exception[1]
File "C:\venv\lib\site-packages\django\core\management\__init__.py", line 337, in execute
autoreload.check_errors(django.setup)()
File "C:\venv\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
fn(*args, **kwargs)
File "C:\venv\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\venv\lib\site-packages\django\apps\registry.py", line 91, in populate
app_config = AppConfig.create(entry)
File "C:\venv\lib\site-packages\django\apps\config.py", line 90, in create
module = import_module(entry)
File "C:\Python\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "C:\venv\myproject\myapp\apps.py", line 2, in <module>
from .scheduler import ScheduledRoutine
File "C:\venv\myproject\myapp\scheduler.py", line 6, in <module>
from .routine import MyRoutine
File "C:\venv\myproject\myapp\routine.py", line 10, in <module>
django.setup()
File "C:\venv\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\venv\lib\site-packages\django\apps\registry.py", line 83, in populate
raise RuntimeError("populate() isn't reentrant")
RuntimeError: populate() isn't reentrant
- Ошибка Nr2:
Поскольку routine.py
находится внутри папки myapp/
, и она пытается сослаться на myproject/settings.py
Я попытался добавить .
(также пробовал ..
) к ссылкекак это:
os.environ["DJANGO_SETTINGS_MODULE"] = ".myproject.settings"
и это:
os.environ["DJANGO_SETTINGS_MODULE"] = "..myproject.settings"
Оба возвращают одинаковые исключения:
TypeError: the 'package' argument is required to perform a relative import for '.myproject.settings'
- Ошибка №3:
Из-за той же проблемы, упомянутой выше (ссылка на settings.py
, то есть myproject/settings.py
), я попытался переместить routine.py
вродительская папка, поэтому мне нужно было изменить импорт в routine.py
и scheduler.py
на их закомментированные версии . Это привело к этому исключению:
ValueError: attempted relative import beyond top-level package
- Ошибка Nr4:
Кроме того, запуск django со следующими комментариями (в рутине .py)
#os.environ["DJANGO_SETTINGS_MODULE"] = "myproject.settings"
#import django
#django.setup()
поднимает django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
в значительной степени то, как все начиналось.
Редактировать: - Ошибка Nr5: Использование этого в рутинном.py вызывает ту же ошибку, что и Nr1.
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_wsgi_application()
Мне кажется очевидным, что проблема в том, как я пытаюсь получить доступ к моделям в routine.py
, а не в планировщике. Что еще я могу попробовать?