2016-12-26 4 views
1

Ich habe eine Programmstruktur identisch mit dem Sellerie django demo, die gut funktioniert. Das Problem ist, dass in meinem DemoApp/tasks.py analog importiere ich ein Modell (from .models import Service), die die am wenigstenSellerie Beat periodische Aufgaben scheitern, wenn die App/tasks.py importiert ein Modell

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. 

Merkwürdigerweise auslöst. Der gesamte Zeitpunkt des Zeitplans besteht darin, die Datenbank zu aktualisieren, indem eine Anforderung an eine API gesendet wird. Nach dem Herausnehmen der Importanweisung und dem Auskommentieren des entsprechenden Codes wird die Aufgabe wie erwartet ausgeführt. Hier ist der Code für das Modell, aber der Fehler tritt auf, egal wie viele Felder das Modell hat, was mich glauben lässt, dass der Fehler nicht auf die Art und Weise zurückzuführen ist, wie das Modell programmiert wird. Ich verfolge Züge.

from django.db import models 

# Create your models here. 

class Service(models.Model): 
    id = models.TextField(primary_key=True) 
    scheduled = models.DateTimeField() 
    expected = models.DateTimeField(null=True, blank=True) # null means cancelled 
    service = models.TextField() 
    platform = models.TextField() 
    origin = models.TextField() 
    dest = models.TextField() 

EDIT: Hier ist meine DemoApp/tasks.py Datei:

# Create your tasks here 
from __future__ import absolute_import, unicode_literals 
from celery import shared_task 
import requests 
from .models import Service 
from django.db import transaction 
import datetime 
import pytz 

def clean(entry): 
    def remove_location_lists(i): 
     """takes care of services with multiple origins or destinations, taking only the first of each.""" 
     if type(i["origin"]["location"]) is list: 
      i["origin"] = i["origin"]["location"][0]["locationName"] 
     else: 
      i["origin"] = i["origin"]["location"]["locationName"] 

     if type(i["dest"]["location"]) is list: 
      i["dest"] = i["dest"]["location"][0]["locationName"] 
     else: 
      i["dest"] = i["dest"]["location"]["locationName"] 

     return i 

    def parse_time(i): 
     """converts the raw time string to a datetime object, and includes some logic to manage crossing midnight.""" 
     if i["expected"] == "Cancelled": 
      i["service"] = "cancelled" 
      i["expected"] = None 
     elif i["expected"] == "Delayed": # blank 
      i["service"] = "delayed" 
      i["expected"] = None 
     else: 
      i["service"] = "ontime" 
      i["expected"] = pytz.utc.localize(datetime.datetime.strptime(i["scheduled"], '%H:%M')) 

     i["scheduled"] = pytz.utc.localize(datetime.datetime.strptime(i["scheduled"], '%H:%M')) 
     i["scheduled"] = i["scheduled"].replace(day=datetime.date.today().day, month=datetime.date.today().month, 
               year=datetime.date.today().year) 

     try: 
      i["expected"] = i["expected"].replace(day=datetime.date.today().day, month=datetime.date.today().month, 
                year=datetime.date.today().year) 

      # include day detection logic! 

     except Exception as inst: 
      pass 

     return i 

    entry = remove_location_lists(entry) 
    entry = parse_time(entry) 

    return entry 

@shared_task 
def get_trips(): 
    print("run task") 
    url = "http://www.southernrailway.com/ajax/departures/json/" 
    get = {'from': 'GTW', 'to': '', 'id': ''} 

    r = requests.post(url, get) 
    json = r.json() 

    unsaved = [] 

    for i in json["arrayServices"]: 
     entry = {'id': i["serviceID"], 
       'scheduled': i["std"], 
       'expected': i["etd"], 
       'service': i["service"], 
       'platform': i["platform"], 
       'origin': i["origin"], 
       'dest': i["destination"]} 

     entry = clean(entry) 

     entry = Service(id=entry['id'], scheduled=entry['scheduled'], expected=entry["expected"], 
         service=entry['service'], platform=entry['platform'], origin=entry['origin'], 
         dest=entry['dest']) 

     unsaved.append(entry) 

    with transaction.atomic(): 
     for i in unsaved: 
      i.save() 

Und für eine gute Maßnahme, hier sind die Inhalte meiner celery.py:

from __future__ import absolute_import, unicode_literals 
import os 
from celery import Celery 
from shitternrailways.tasks import get_trips 

# set the default Django settings module for the 'celery' program. 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'arlyon.settings') 

app = Celery('arlyon') 

# Using a string here means the worker don't have to serialize 
# the configuration object to child processes. 
# - namespace='CELERY' means all celery-related configuration keys 
# should have a `CELERY_` prefix. 
app.config_from_object('django.conf:settings', namespace='CELERY') 

@app.on_after_configure.connect 
def setup_periodic_tasks(sender, **kwargs): 
    sender.add_periodic_task(1, get_trips.s(), name="get trips") 

# Load task modules from all registered Django app configs. 
app.autodiscover_tasks() 

@app.task(bind=True) 
def debug_task(self): 
    print('Request: {0!r}'.format(self.request)) 

und schließlich die vollständige traceback:

/Users/v/Documents/programming/venvs/arlyon/bin/python /Users/v/Documents/programming/arlyon/manage.py runserver 8000 
Traceback (most recent call last): 
    File "/Users/v/Documents/programming/arlyon/manage.py", line 22, in <module> 
    execute_from_command_line(sys.argv) 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line 
    utility.execute() 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/core/management/__init__.py", line 302, in execute 
    settings.INSTALLED_APPS 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/conf/__init__.py", line 55, in __getattr__ 
    self._setup(name) 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/conf/__init__.py", line 43, in _setup 
    self._wrapped = Settings(settings_module) 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/conf/__init__.py", line 99, in __init__ 
    mod = importlib.import_module(self.SETTINGS_MODULE) 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/importlib/__init__.py", line 126, in import_module 
    return _bootstrap._gcd_import(name[level:], package, level) 
    File "<frozen importlib._bootstrap>", line 986, in _gcd_import 
    File "<frozen importlib._bootstrap>", line 969, in _find_and_load 
    File "<frozen importlib._bootstrap>", line 944, in _find_and_load_unlocked 
    File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed 
    File "<frozen importlib._bootstrap>", line 986, in _gcd_import 
    File "<frozen importlib._bootstrap>", line 969, in _find_and_load 
    File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked 
    File "<frozen importlib._bootstrap>", line 673, in _load_unlocked 
    File "<frozen importlib._bootstrap_external>", line 665, in exec_module 
    File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed 
    File "/Users/v/Documents/programming/arlyon/arlyon/__init__.py", line 5, in <module> 
    from .celery import app as celery_app 
    File "/Users/v/Documents/programming/arlyon/arlyon/celery.py", line 4, in <module> 
    from shitternrailways.tasks import get_trips 
    File "/Users/v/Documents/programming/arlyon/shitternrailways/tasks.py", line 5, in <module> 
    from .models import Service 
    File "/Users/v/Documents/programming/arlyon/shitternrailways/models.py", line 5, in <module> 
    class Service(models.Model): 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/db/models/base.py", line 94, in __new__ 
    app_config = apps.get_containing_app_config(module) 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/apps/registry.py", line 239, in get_containing_app_config 
    self.check_apps_ready() 
    File "/Users/v/Documents/programming/venvs/arlyon/lib/python3.5/site-packages/django/apps/registry.py", line 124, in check_apps_ready 
    raise AppRegistryNotReady("Apps aren't loaded yet.") 
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. 

Process finished with exit code 1 

A Die Suche hat nur wenig Hilfe gezeigt, was wahrscheinlich darauf zurückzuführen ist, wie jung Sellerie 4 ist. Also wandte ich mich an euch. Danke für deine Tipps.

Antwort

1

Sie verwenden @shared_task Dekorateur für die Aufgabe. Dies bedeutet, dass die Aufgabe keiner Anwendung zugeordnet ist. In sellery.py versuchen Sie jedoch, diese Aufgabe für den Beat-Scheduler zu verwenden, und Sie erhalten einen Fehler.

Ich sehe zwei mögliche Wege, um es zu lösen. Zunächst können Sie diese Aufgabe von demoapp in sellery.py verschieben und mit @ app.task decorator verwenden.

Zweitens können Sie versuchen, von der App aus auf die Aufgabe zuzugreifen. Dafür haben Sie app.autodiscover_tasks() aufgerufen. Dies bedeutet, dass Aufgaben in die App geladen werden. So können Sie versuchen:

@app.on_after_configure.connect 
def setup_periodic_tasks(sender, **kwargs): 
    sender.add_periodic_task(1, app.tasks["demoapp.get_trips"], name="get trips") 

Allerdings muss es getestet werden. Ich habe es nicht in meiner Maschine versucht. Viel Glück!

+0

Die Aufgaben werden geladen, ich kann jedoch nicht mit der von Ihnen bereitgestellten Methode auf die Aufgabe zugreifen. Obwohl ich bestätigen kann, dass es existiert (speziell in app.tasks ["demoapp.tasks.get_trips"]), kann ich die Aufgabe nicht registrieren. Ich kann weiterhin Tasks definieren, die in der sellery.py-Datei definiert sind (z. B. die Debug-Task), daher muss es der Name der Task sein. Es soll eine Signaturdatei aufnehmen. Ist app.tasks ["demoapp.tasks.get_trips"] eine Signaturdatei? Aufruf von app.tasks ["demoapp.tasks.get_trips"]. S() tut nichts. – arlyon

+0

Es ist nervig, wie wenig Informationen im Sellerie-Fenster gegeben sind, selbst mit -l debug. – arlyon

+0

Sellerie hat eine lokale Registrierung der Aufgabennamen. Die Art, wie du darauf zugreifst, sieht für mich nicht korrekt aus. Ich denke, es sollte nicht app.tasks ["demoapp.tasks.get_trips"] sein. Der korrekte Name, den Sie sehen können, wenn der Standard-Worker gestartet wird. Auch hier gibt es Infos dazu http://docs.selleryproject.org/en/latest/userguide/application.html –

Verwandte Themen