2014-09-03 16 views
10

Ho usato per avere una funzione come questasedano e segnali

def calculate(self, input): 
    result = input * 2 

    if result > 4: 
     result_higher_then_four.send(result) 

    return result 

Dove result_higher_then_four rappresenta ovviamente un segnale.

Poi ho introdotto il sedano e la mia funzione sembrava di seguito e non ho mai ricevuto un segnale di nuovo. Suppongo che i segnali siano legati per processo e mentre il sedano gira in un processo diverso, questo significa che non posso prendere il segnale nel processo principale. Devo usare un thread_local per risolvere questo? O sto trascurando l'ovvio?

Grazie

@task 
def calculate(self, input): 
    result = input * 2 

    if result > 4: 
     result_higher_then_four.send(result) 

    return result 
+0

@ChillarAnand sì – user2298943

risposta

2

Il problema è che il ricevitore del segnale non viene registrato. I lavoratori del sedano funzionano nel loro stesso processo, quindi le connessioni del segnale devono essere fatte in quel processo. Se sai cosa sono o li puoi scoprire, puoi registrarli durante l'inizializzazione dell'attività utilizzando this technique.

Ovviamente, questo elimina alcuni dei vantaggi dell'utilizzo dei segnali in primo luogo perché è necessario conoscere le connessioni in anticipo.

Un'idea è di assumere che i ricevitori di segnale si registreranno sempre nel modulo dei modelli di ciascuna app. Nel qual caso funzionerà.

class CalculateTask(celery.Task): 

    def __init__(self): 
     from django.conf import settings 
     for app in settings.INSTALLED_APPS: 
      app_models = '{}.{}'.format(app,'models') 
      __import__(app_models, globals=globals())         

    def run(self, input): 
     result = input * 2 
     if result > 4: 
      result_higher_then_four.send(result) 

     return result 
0

se ho capito bene che si desidera lo stesso processo per inviare ans ricevere il segnale inviato? in tal caso, perché non utilizzare:

os.kill(os.getpid(), signal.SIGUSER1) 

e definire di conseguenza il gestore per SIGUSR1?

se si desidera un altro processo per ottenerlo è necessario avere il suo pid in ogni caso per inviare segnali ad esso in modo da utilizzare solo lo stesso comando che ho dato qui con il pid corretto invece di os.getpid(). A meno che non mi sia sfuggito qualcosa?

2

È possibile utilizzare il segnale celeryd_init per inizializzare i vostri lavoratori e segnali http://celery.readthedocs.org/en/latest/userguide/signals.html#celeryd-init

in base a ciò che hai fornito, ho provato con:

from celery.signals import celeryd_init 
from celery.utils.dispatch import Signal 

def process_result(result, *args, **kwargs): 
    print "signals received: %s" % result 

result_higher_then_four = Signal() 

@celeryd_init.connect 
def init_signals(*args, **kwargs): 
    result_higher_then_four.connect(process_result) 

@task(bind=True) 
def calculate(self, input): 
    result = input * 2 

    if result > 4: 
     result_higher_then_four.send(result=result, sender=self) 

    return result 
+0

Questo è corretto . Penso che l'OP potrebbe anche usare la catena per ottenere la stessa cosa ma molto leggibile. Vedi esempio qui http://docs.celeryproject.org/en/latest/userguide/tasks.html#avoid-launching-synchronous-subtasks – chhantyal