2010-11-27 19 views
8

मैं एक ऐप लिख रहा हूं जो उपयोगकर्ता को फ़ाइल में डेटा अपलोड करने की अनुमति देगा; ऐप इस डेटा को संसाधित करेगा, और परिणामों को उपयोगकर्ता को ईमेल करेगा। प्रसंस्करण में कुछ समय लग सकता है, इसलिए मैं इसे पूरा करने के लिए दृश्य में प्रतीक्षा करने के बजाय इसे पाइथन लिपि में अलग से संभालना चाहता हूं। पायथन स्क्रिप्ट और दृश्य को संवाद करने की आवश्यकता नहीं है क्योंकि स्क्रिप्ट दृश्य द्वारा लिखी गई फ़ाइल से डेटा उठाएगी। दृश्य सिर्फ "आपके डेटा को अपलोड करने के लिए धन्यवाद" जैसे संदेश भेजेगा - परिणाम आपको ईमेल किए जाएंगे "Django: क्या मुझे एक अलग प्रक्रिया को बंद करना चाहिए?

Django में ऐसा करने का सबसे अच्छा तरीका क्या है? एक अलग प्रक्रिया से बाहर निकलना? एक कतार पर कुछ रखो?

कुछ उदाहरण कोड की सराहना की जाएगी। धन्यवाद।

+0

कुछ त्रुटि तब होती है, तो आप डेटा कार्रवाई कर रहे हैं, जबकि क्या है? –

+0

मैं उन्हें इसके बारे में ईमेल करूंगा। मैं उनसे वेब पेज पर इंतजार नहीं कर सकता जब तक कि यह समाप्त नहीं हो जाता है क्योंकि इसमें 20 मिनट या उससे अधिक समय लग सकता है। – FunLovinCoder

उत्तर

17

सरल संभव समाधान एक कस्टम commands खोज करता है लिखने के लिए है:

allThreads = [] 

# ... 

global allThreads 
thread = Thread(target=SlowProcessingFunction, args=(), kwargs={}) 
thread.start() 
allThreads.append(thread) 

आप जब thread.is_alive() रिटर्न False सूची से धागे को हटा सकते हैं सभी अन-संसाधित फ़ाइलें, उन्हें संसाधित करती हैं और फिर उपयोगकर्ता को ईमेल करती हैं। प्रबंधन आदेश Django ढांचे के अंदर चलाता है ताकि उनके पास सभी मॉडलों, डीबी कनेक्शन इत्यादि तक पहुंच हो, लेकिन आप उन्हें कहीं से भी कॉल कर सकते हैं, उदाहरण के लिए crontab।

यदि आपको फ़ाइल अपलोड करने और प्रसंस्करण शुरू होने के बीच समय सीमा के बारे में परवाह है, तो आप Celery जैसे ढांचे का उपयोग कर सकते हैं, जो मूल रूप से एक संदेश कतार का उपयोग करने के लिए एक सहायक लाइब्रेरी है और कतार में श्रमिकों को सुन रहा है। यह बहुत कम विलंबता होगी, लेकिन दूसरी ओर, सादगी आपके लिए अधिक महत्वपूर्ण हो सकती है।

मैं आपके विचारों में थ्रेड या स्पॉन्गिंग प्रक्रिया शुरू करने के खिलाफ दृढ़ता से सलाह दूंगा, क्योंकि धागे django प्रक्रिया के अंदर चल रहे होंगे और आपके वेबसर्वर को नष्ट कर सकते हैं (आपकी कॉन्फ़िगरेशन के आधार पर)। बाल प्रक्रिया Django प्रक्रिया से सबकुछ हासिल करेगी, जिसे आप शायद नहीं चाहते हैं। यह सामान अलग रखना बेहतर है।

+0

हां, मैं इसे जितना संभव हो उतना आसान बनाना चाहता हूं लेकिन मुझे एहसास नहीं हुआ कि प्रक्रिया को हल करने के परिणाम या धागे इतने गंभीर हो सकते हैं। सर उठाने के लिए धन्यवाद। सेलेरी के लिए – FunLovinCoder

+0

+1। कतार यहां जाने का रास्ता है। –

3

प्रसंस्करण करने के लिए आप thread को स्पॉन कर सकते हैं। Django के साथ वास्तव में बहुत कुछ नहीं होगा; दृश्य समारोह को कार्यकर्ता धागे को लात मारने की आवश्यकता होगी और यही वह है।

यदि आप वास्तव में एक अलग प्रक्रिया चाहते हैं, तो आपको subprocess मॉड्यूल की आवश्यकता होगी। लेकिन क्या आपको वास्तव में मानक I/O को पुनर्निर्देशित करने की आवश्यकता है या बाहरी प्रक्रिया नियंत्रण की अनुमति है?

उदाहरण:

from threading import Thread 
from MySlowThing import SlowProcessingFunction # or whatever you call it 

# ... 

Thread(target=SlowProcessingFunction, args=(), kwargs={}).start() 

मैं एक कार्यक्रम है जहाँ मैं धागे की प्रगति ट्रैक करना नहीं चाहता था नहीं किया है, इसलिए मैं अगर यह Thread वस्तु कहीं भंडारण के बिना काम करता पता नहीं है। आपको लगता है कि क्या करने की जरूरत है, तो यह बहुत सरल है:

def cull_threads(): 
    global allThreads 
    allThreads = [thread for thread in allThreads if thread.is_alive()] 
+0

मुझे सिर्फ एक अजगर लिपि को बंद करने की आवश्यकता है और इसके बारे में भूल जाओ। मुझे इसके साथ संवाद करने की आवश्यकता नहीं है क्योंकि यह दृश्य में लिखे गए फ़ाइल से डेटा उठाएगा। क्या आप कृपया कुछ उदाहरण कोड जोड़ सकते हैं? – FunLovinCoder

+0

क्या यह एक पूरी तरह से अलग पायथन लिपि है, या आप इसे मॉड्यूल के रूप में आयात कर सकते हैं और इसे कॉल कर सकते हैं? –

+0

@ माइक डीसिमोन। यह एक पूरी तरह से अलग पायथन लिपि है, लेकिन न्यूटिन से फीडबैक के बाद संभवतः एक प्रो या थ्रेड को नहीं बढ़ाना सबसे अच्छा है। – FunLovinCoder

4

वर्तमान में मेरे पास समान आवश्यकताओं (बस अधिक जटिल ^^) वाला एक प्रोजेक्ट है।

अपने Django व्यू से कभी भी उपप्रोसेसर या धागे को जन्म न दें। आपके पास Django प्रक्रियाओं पर कोई नियंत्रण नहीं है और कार्य के अंत से पहले इसे मार दिया जा सकता है, रोका जा सकता है। यह वेब सर्वर द्वारा नियंत्रित होता है (उदा। डब्लूएसजीआई के माध्यम से अपाचे)।

मैं जो करता हूं वह बाहरी स्क्रिप्ट है, जो एक अलग प्रक्रिया में चलती है।आपके पास दो समाधान हैं जो मुझे लगता है:

  • एक ऐसी प्रक्रिया जो हमेशा चल रही है और निर्देशिका को क्रॉल कर रही है जहां आप अपनी फाइलें डालते हैं। उदाहरण के लिए यह प्रत्येक दस सेकंड में निर्देशिका की जांच करेगा और फ़ाइलों को संसाधित करेगा
  • उपर्युक्त जैसा ही है, लेकिन हर एक्स सेकंड क्रॉन द्वारा चलाया जाता है। यह मूल रूप से एक ही प्रभाव है
  • कार्यकर्ता प्रक्रियाओं को बनाने और अपने Django आवेदन के साथ कतार में नौकरियां जोड़ने के लिए सेलेरी का उपयोग करें। फिर आपको सेलेरी के साथ उपलब्ध साधनों में से एक परिणाम वापस प्राप्त करने की आवश्यकता होगी।

अब आपको अंत में उपयोगकर्ता को ईमेल करने के लिए Django मॉडल में जानकारी तक पहुंचने की आवश्यकता है।

  • बाहरी स्क्रिप्ट
  • से अपने मॉड्यूल (मॉडल आदि) आयात एक कस्टम आदेश के रूप में बाहरी स्क्रिप्ट को लागू करें (के रूप में knutin सुझाव)
  • के माध्यम से Django आवेदन करने के लिए परिणाम के बारे में बताएँ: यहां आप कई समाधान है उदाहरण के लिए एक POST अनुरोध। फिर आप एक सामान्य Django दृश्य में ईमेल भेजने और स्थिति परिवर्तन आदि करेंगे।

मैं बाहरी प्रक्रिया के लिए जाउंगा और मॉड्यूल या POST अनुरोध आयात करूंगा। इस तरह यह अधिक लचीला है। उदाहरण के लिए आप एक ही समय में कई फ़ाइलों को संसाधित करने के लिए मल्टीप्रोसेसिंग मॉड्यूल का उपयोग कर सकते हैं (इस प्रकार बहु-कोर मशीनों का कुशलतापूर्वक उपयोग कर सकते हैं)।

एक बुनियादी कार्यप्रवाह होगा:

  1. नई फ़ाइलों के लिए निर्देशिका
  2. प्रत्येक फ़ाइल के लिए (parallelized किया जा सकता) की जांच:
    1. प्रक्रिया
    2. ईमेल भेजें या अपने Django आवेदन को सूचित
  3. थोड़ी देर के लिए सोएं

मेरी परियोजना में वास्तव में सीपीयू-मांग प्रसंस्करण शामिल है। मैं वर्तमान में एक बाहरी प्रक्रिया का उपयोग करता हूं जो कार्यकर्ता प्रक्रियाओं के पूल में प्रोसेसिंग जॉब्स देता है (यह मूल रूप से सेलेरी आपके लिए क्या कर सकता है) और POST अनुरोधों के माध्यम से प्रगति की रिपोर्ट करता है और Django आवेदन पर वापस आ जाता है। यह वास्तव में अच्छी तरह से काम करता है और अपेक्षाकृत स्केलेबल है, लेकिन जल्द ही मैं क्लस्टर पर सेलेरी का उपयोग करने के लिए इसे बदल दूंगा।

+0

महान प्रतिक्रिया के लिए धन्यवाद। मुझे बड़ी फ़ाइलों के लिए एकाधिक धागे को लात मारने की आवश्यकता हो सकती है, इसलिए मल्टीप्रोसेसिंग मॉड्यूल को देखेंगे। – FunLovinCoder

+0

यदि प्रसंस्करण सीपीयू-सीमित है, तो आपको प्रक्रियाओं का उपयोग करना होगा (उदा। प्रोसेसिंग मॉड्यूल के साथ) और धागे (थ्रेडिंग मॉड्यूल) नहीं। पायथन ग्लोबल इंटरप्रेटर लॉक धागे को समानांतर में वास्तव में चलाने के लिए रोकता है, इसलिए कोई प्रदर्शन वृद्धि नहीं होती है (मुझे लगता है कि मेरी परियोजना करते समय मुझे एहसास हुआ)। –

+0

इसके अलावा, सेलेरी जाने का रास्ता हो सकता है, क्योंकि यह मेरे द्वारा स्वचालित रूप से वर्णित बहुत सारे काम करता है। केवल एक चीज यह है कि आपको यह समझना होगा कि परिणाम कैसे प्राप्त करें क्योंकि आप कार्य को समाप्त करने की प्रतीक्षा नहीं कर सकते हैं (एक HTTP कॉलबैक आसानी से मुझे लगता है)। –

1

आप मल्टीप्रोसेसिंग का उपयोग कर सकते हैं। http://docs.python.org/library/multiprocessing.html

अनिवार्य रूप से,

def _pony_express(objs, action, user, foo=None): 
    # unleash the beasts 

def bulk_action(request, t): 

    ... 
    objs = model.objects.filter(pk__in=pks) 

    if request.method == 'POST': 
     objs.update(is_processing=True) 

     from multiprocessing import Process 
     p = Process(target=_pony_express, args=(objs, action, request.user), kwargs={'foo': foo}) 
     p.start() 

     return HttpResponseRedirect(next_url) 

    context = {'t': t, 'action': action, 'objs': objs, 'model': model} 
    return render_to_response(...) 
संबंधित मुद्दे