2009-05-04 11 views
10

यदि मेरे पास कोई प्रोग्राम है जो थ्रेडिंग और कतार का उपयोग करता है, तो निष्पादन को रोकने के लिए मुझे अपवाद कैसे प्राप्त होते हैं? यहां एक उदाहरण प्रोग्राम है, जो ctrl-c के साथ रुकना संभव नहीं है (मूल रूप से पायथन दस्तावेज़ों से फिसल गया)।थ्रेडिंग और कतार का उपयोग करते समय मैं अपवादों को कैसे संभाल सकता हूं?

from threading import Thread 
from Queue import Queue 
from time import sleep 

def do_work(item): 
    sleep(0.5) 
    print "working" , item 

def worker(): 
     while True: 
      item = q.get() 
      do_work(item) 
      q.task_done() 

q = Queue() 

num_worker_threads = 10 

for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    # t.setDaemon(True) 
    t.start() 

for item in range(1, 10000): 
    q.put(item) 

q.join()  # block until all tasks are done 

उत्तर

6

सबसे आसान तरीका डेमॉन धागे के रूप में सभी कार्यकर्ता धागे शुरू करने के लिए है, तो बस अपने मुख्य पाश

while True: 
    sleep(1) 

हो साधते Ctrl + C अपने मुख्य थ्रेड में एक अपवाद फेंक देंगे, और सभी जब दुभाषिया निकलता है तो डेमॉन धागे से बाहर निकल जाएगा। यह मानता है कि आप उन सभी धागे में बाहर निकलने से पहले सफाई नहीं करना चाहते हैं।

एक अधिक जटिल तरीका है करने के लिए है एक वैश्विक stoppedEvent:

stopped = Event() 
def worker(): 
    while not stopped.is_set(): 
     try: 
      item = q.get_nowait() 
      do_work(item) 
     except Empty:  # import the Empty exception from the Queue module 
      stopped.wait(1) 

फिर अपने मुख्य पाश जब यह एक KeyboardInterrupt

try: 
    while not stopped.is_set(): 
     stopped.wait(1) 
except KeyboardInterrupt: 
    stopped.set() 

यह आपके कार्यकर्ता की सुविधा देता है हो जाता है False को stopped घटना सेट कर सकते हैं धागे खत्म हो जाते हैं जो वे कर रहे हैं आप चाहते हैं कि केवल प्रत्येक कार्यकर्ता धागा एक डिमन हो और निष्पादन के बीच में बाहर निकलें। आप जो भी सफाई चाहते हैं वह भी कर सकते हैं।

ध्यान दें कि यह उदाहरण q.join() का उपयोग नहीं करता है - इससे चीजें अधिक जटिल होती हैं, हालांकि आप अभी भी इसका उपयोग कर सकते हैं। यदि आप करते हैं तो KeyboardInterrupt एस का पता लगाने के अपवादों के बजाय सिग्नल हैंडलर का उपयोग करना आपकी सबसे अच्छी शर्त है। उदाहरण के लिए:

from signal import signal, SIGINT 
def stop(signum, frame): 
    stopped.set() 
signal(SIGINT, stop) 

इस की मदद से आप को परिभाषित जब आप को प्रभावित करने वाले जो कुछ भी अपने मुख्य पाश के बीच में है बिना Ctrl + C मारा क्या होता है। तो आप Ctrl + C द्वारा बाधित होने के बारे में चिंता किए बिना q.join() कर सकते हैं। बेशक, मेरे उपरोक्त उदाहरणों के साथ, आपको शामिल होने की आवश्यकता नहीं है, लेकिन आपके पास ऐसा करने का कोई अन्य कारण हो सकता है।

+1

तो, मूल रूप से, q.join() का उपयोग करके धागे में अपवादों को संभालना मुश्किल हो जाता है? –

+1

क्या यह पढ़ना नहीं चाहिए "सिग्नल (सिगिनट, स्टॉप)"? – Ber

+0

यह चीजों को और अधिक जटिल बनाता है, लेकिन मैंने आपको यह दिखाने के लिए सिग्नल के साथ एक उदाहरण जोड़ा है कि आप q.join() का उपयोग कैसे करेंगे यदि आपके पास इसका उपयोग करने का एक अच्छा कारण था। –

1

एक (संभवतः) से Offtopic ध्यान दें:

(...) 
for item in range(1, 10000): 
    q.put(item) 
(...) 

आप xrange बजाय रेंज यहां इस्तेमाल कर सकते हैं (जब तक आप python3000 उपयोग करें)। आप ऐसा करके कुछ सीपीयू और मेमोरी को बचाएंगे। Xrange पर अधिक here पाया जा सकता है।

संबंधित मुद्दे

 संबंधित मुद्दे