2017-07-04 8 views
10

पर एक फ़ंक्शन चलाएं मैं Django ऐप पर काम कर रहा हूं। मेरे पास एक एपीआई एंडपॉइंट है, जो अनुरोध किया गया है, उसे एक फ़ंक्शन करना होगा जिसे कुछ बार दोहराया जाना चाहिए (जब तक कि कोई निश्चित शर्त सत्य न हो)। कैसे मैं इसके साथ अभी काम कर रहा हूँ है -Django - प्रत्येक x सेकंड

def shut_down(request): 
    # Do some stuff 
    while True: 
    result = some_fn() 
    if result: 
     break 
    time.sleep(2) 

    return True 

मुझे पता है कि यह एक भयानक दृष्टिकोण है और मैं 2 सेकंड के लिए अवरुद्ध नहीं किया जाना चाहिए कि, मैं समझ नहीं इसके चारों ओर पाने के लिए ।
यह 4 सेकंड का इंतजार करने के बाद, यह काम करता है। लेकिन मुझे ऐसा कुछ चाहिए जो लूप को पृष्ठभूमि में चल रहा है, और कुछ_fn सही होने पर रोकें। (साथ ही, यह निश्चित है कि कुछ_एफएन सही हो जाएंगे)

EDIT -
पढ़ना ओज़ 123 की प्रतिक्रिया ने मुझे एक ऐसा विचार दिया जो काम करने लगता है। यहाँ मैं क्या किया है -

def shut_down(params): 
    # Do some stuff 
    # Offload the blocking job to a new thread 

    t = threading.Thread(target=some_fn, args=(id,), kwargs={}) 
    t.setDaemon(True) 
    t.start() 

    return True 

def some_fn(id): 
    while True: 
     # Do the job, get result in res 
     # If the job is done, return. Or sleep the thread for 2 seconds before trying again. 

     if res: 
      return 
     else: 
      time.sleep(2) 

यह मेरे लिए काम करता है। यह आसान है लेकिन मुझे नहीं पता कि मल्टीथ्रेडिंग Django के साथ संयोजन में कितनी कुशल है।
यदि कोई इस के नुकसान को इंगित कर सकता है, तो आलोचना की सराहना की जाती है।

+1

आप इसके लिए अजवाइन का उपयोग कर सकते हैं। आप यहां मैनुअल पा सकते हैं: https://realpython.com/blog/python/asynchronous-tasks-with-django-and-celery/#periodic-tasks – neverwalkaloner

+0

@neverwalkaloner मुझे बिल्कुल वही पसंद है जैसा मुझे चाहिए। इसका उपयोग करने की कोशिश करेंगे, धन्यवाद। :) – Zeokav

+1

जैसा कि @neverwalkaloner द्वारा उल्लिखित है, आप अजवाइन का उपयोग कर सकते हैं, आप अनुसूची के साथ आवधिक कार्य सेट कर सकते हैं, दस्तावेज़ को बहुत लचीला है http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html इसे crontab मॉड्यूल के लिए एक नज़र दें। –

उत्तर

5

अजवाइन एक से अधिक को मार है:

सेट करने के बाद आप के लिए कोड बदल सकते हैं। उन परियोजनाओं के लिए आप schedule का उपयोग कर सकते हैं, इसका उपयोग करना बहुत आसान है।

इस पुस्तकालय आप किसी भी समारोह समय-समय पर कार्य निष्पादित कर सकते हैं के साथ

:

import schedule 
import time 

def job(): 
    print("I'm working...") 

schedule.every(10).minutes.do(job) 
schedule.every().hour.do(job) 
schedule.every().day.at("10:30").do(job) 
schedule.every().monday.do(job) 
schedule.every().wednesday.at("13:15").do(job) 

while True: 
    schedule.run_pending() 
    time.sleep(1) 

उदाहरण एक अवरुद्ध ढंग से चलाता है, लेकिन अगर आप सवाल जवाब में देखें, तो आप यह है कि आप भी कार्य चला सकते हैं मिलेगा एक समानांतर धागा, इस तरह है कि आप अवरुद्ध नहीं कर रहे हैं, और अब और काम एक बार की जरूरत नहीं निकालें: अनुसूची आयात समयबद्धक

def run_continuously(self, interval=1): 
    """Continuously run, while executing pending jobs at each elapsed 
    time interval. 
    @return cease_continuous_run: threading.Event which can be set to 
    cease continuous run. 
    Please note that it is *intended behavior that run_continuously() 
    does not run missed jobs*. For example, if you've registered a job 
    that should run every minute and you set a continuous run interval 
    of one hour then your job won't be run 60 times at each interval but 
    only once. 
    """ 

    cease_continuous_run = threading.Event() 

    class ScheduleThread(threading.Thread): 

     @classmethod 
     def run(cls): 
      while not cease_continuous_run.is_set(): 
       self.run_pending() 
       time.sleep(interval) 

    continuous_thread = ScheduleThread() 
    continuous_thread.setDaemon(True) 
    continuous_thread.start() 
    return cease_continuous_run 


Scheduler.run_continuously = run_continuously 

यहाँ से एक वर्ग विधि में उपयोग के लिए एक उदाहरण है:

def foo(self): 
     ... 
     if some_condition(): 
      return schedule.CancelJob # a job can dequeue it 

    # can be put in __enter__ or __init__ 
    self._job_stop = self.scheduler.run_continuously() 

    logger.debug("doing foo"...) 
    self.foo() # call foo 
    self.scheduler.every(5).seconds.do(
     self.foo) # schedule foo for running every 5 seconds 

    ... 
    # later on foo is not needed any more: 
    self._job_stop.set() 

    ... 

    def __exit__(self, exec_type, exc_value, traceback): 
     # if the jobs are not stop, you can stop them 
     self._job_stop.set() 
+0

वास्तव में, मैं सेलेरी से बचने के तरीकों की तलाश कर रहा था (अभी के लिए) क्योंकि मुझे केवल अपनी परियोजना में एक या दो स्थानों में शेड्यूलिंग की आवश्यकता है। मैं बस इस हाहा की तरह कुछ आया! मैं इसे लागू करने का प्रयास करूंगा और यदि मेरे कोई प्रश्न हैं तो वापस वापस आ जाएंगे। आपके उत्तर के लिए धन्यवाद! :) – Zeokav

+0

मैंने नीचे एक उत्तर पोस्ट किया। मैं इसकी सराहना करता हूं अगर आप मुझे बता सकते हैं कि क्या संभावित रूप से बाद में समस्याएं पैदा हो सकती हैं। – Zeokav

+0

दिलचस्प सम्मेलन - किसी भी कारण से आप एक ऐसी कक्षा नहीं बना रहे हैं जो 'शेड्यूलर 'से विरासत में है जो' run_continuously' विधि जोड़ता है? यह थोड़ा और तुरंत स्पष्ट हो रहा है कि क्या होगा। – Tim

1

मैं आपको सेलरी के task प्रबंधन का उपयोग करने की सलाह देता हूं। यदि आप जावास्क्रिप्ट पृष्ठभूमि से हैं तो इस ऐप को सेट करने के लिए आप this देख सकते हैं (पैकेज)। कई छोटी परियोजनाओं के लिए

@app.task 
def check_shut_down(): 
    if not some_fun(): 
     # add task that'll run again after 2 secs 
     check_shut_down.delay((), countdown=3) 
    else: 
     # task completed; do something to notify yourself 
     return True 
संबंधित मुद्दे