2013-03-12 5 views
11

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

Multiprocessing

मेरे पहले प्रयास के साथ था निर्मित multiprocessing मॉड्यूल है, लेकिन इस धागे लेकिन subprocesses उपयोग नहीं करता है के रूप में के बजाय हम इस समस्या वस्तुओं है कि मसालेदार नहीं किया जा सकता में चलाने। यहाँ नहीं जाओ

from multiprocessing import Pool 

class Sample(object): 
    def compute_fib(self, n): 
     phi = (1 + 5**0.5)/2 
     self.fib = int(round((phi**n - (1-phi)**n)/5**0.5)) 

samples = [Sample() for i in range(8)] 
pool = Pool(processes=8) 
for s in samples: pool.apply_async(s.compute_fib, [20]) 
pool.join() 
for s in samples: print s.fib 

# PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed 

वायदा

तो मैं देख रहा हूँ अजगर 3.2 here की ठंडी समवर्ती सुविधाओं में से कुछ की एक पीठ बंदरगाह है। यह उपयोग करने के लिए सही और सरल लगता है। समस्या यह है कि जब आप किसी एक श्रमिक में अपवाद प्राप्त करते हैं, तो आपको केवल "ज़ीरोडिविजन एरर" जैसे अपवाद का प्रकार मिलता है लेकिन कोई ट्रेसबैक नहीं होता है और इस प्रकार किसी भी संकेत का कोई संकेत अपवाद का कारण नहीं बनता है। कोड डीबग करना असंभव हो जाता है। नही जाओ।

from concurrent import futures 

class Sample(object): 
    def compute_fib(self, n): 
     phi = (1 + 5**0.5)/2 
     1/0 
     self.fib = int(round((phi**n - (1-phi)**n)/5**0.5)) 

samples = [Sample() for i in range(8)] 
pool = futures.ThreadPoolExecutor(max_workers=8) 
threads = [pool.submit(s.compute_fib, 20) for s in samples] 
futures.wait(threads, return_when=futures.FIRST_EXCEPTION) 
for t in threads: t.result() 
for s in samples: print s.fib 


# futures-2.1.3-py2.7.egg/concurrent/futures/_base.pyc in __get_result(self) 
# 354  def __get_result(self): 
# 355   if self._exception: 
#--> 356    raise self._exception 
# 357   else: 
# 358    return self._result 
# 
# ZeroDivisionError: integer division or modulo by zero 

WorkerPool

मैं इस पैटर्न here का एक अन्य कार्यान्वयन पाया। इस बार जब कोई अपवाद होता है तो यह मुद्रित होता है, लेकिन फिर मेरा आईपीथॉन इंटरैक्टिव दुभाषिया एक लटकते राज्य में छोड़ा जाता है और उसे दूसरे खोल से मारने की आवश्यकता होती है। नही जाओ।

import workerpool 

class Sample(object): 
    def compute_fib(self, n): 
     phi = (1 + 5**0.5)/2 
     1/0 
     self.fib = int(round((phi**n - (1-phi)**n)/5**0.5)) 

samples = [Sample() for i in range(8)] 
pool = workerpool.WorkerPool(size=8) 
for s in samples: pool.map(s.compute_fib, [20]) 
pool.wait() 
for s in samples: print s.fib 

# ZeroDivisionError: integer division or modulo by zero 
# ^C^C^C^C^C^C^C^C^D^D 
# $ kill 1783 

ThreadPool

फिर भी एक अन्य कार्यान्वयन here। इस बार जब कोई अपवाद होता है, तो यह stderr पर मुद्रित होता है लेकिन स्क्रिप्ट को बाधित नहीं किया जाता है और इसके बजाय निष्पादन जारी रहता है, जो अपवाद के उद्देश्य को रोकता है और चीजों को असुरक्षित बना सकता है। अभी भी प्रयोग योग्य नहीं है।

import threadpool 

class Sample(object): 
    def compute_fib(self, n): 
     phi = (1 + 5**0.5)/2 
     1/0 
     self.fib = int(round((phi**n - (1-phi)**n)/5**0.5)) 

samples = [Sample() for i in range(8)] 
pool = threadpool.ThreadPool(8) 
requests = [threadpool.makeRequests(s.compute_fib, [20]) for s in samples] 
requests = [y for x in requests for y in x] 
for r in requests: pool.putRequest(r) 
pool.wait() 
for s in samples: print s.fib 

# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
# ZeroDivisionError: integer division or modulo by zero 
#---> 17 for s in samples: print s.fib 
# 
#AttributeError: 'Sample' object has no attribute 'fib' 

- अपडेट -

ऐसा लगता है कि futures पुस्तकालय के विषय में, अजगर 3 के व्यवहार अजगर 2.

futures_exceptions.py के समान नहीं है:

from concurrent.futures import ThreadPoolExecutor, as_completed 

def div_zero(x): 
    return x/0 

with ThreadPoolExecutor(max_workers=4) as executor: 
    futures = executor.map(div_zero, range(4)) 
    for future in as_completed(futures): print(future) 

अजगर 2.7.6 आउटपुट:

Traceback (most recent call last): 
    File "...futures_exceptions.py", line 12, in <module> 
    for future in as_completed(futures): 
    File "...python2.7/site-packages/concurrent/futures/_base.py", line 198, in as_completed 
    with _AcquireFutures(fs): 
    File "...python2.7/site-packages/concurrent/futures/_base.py", line 147, in __init__ 
    self.futures = sorted(futures, key=id) 
    File "...python2.7/site-packages/concurrent/futures/_base.py", line 549, in map 
    yield future.result() 
    File "...python2.7/site-packages/concurrent/futures/_base.py", line 397, in result 
    return self.__get_result() 
    File "...python2.7/site-packages/concurrent/futures/_base.py", line 356, in __get_result 
    raise self._exception 
ZeroDivisionError: integer division or modulo by zero 

अजगर 3.3.2 उत्पादन:

Traceback (most recent call last): 
    File "...futures_exceptions.py", line 11, in <module> 
    for future in as_completed(futures): 
    File "...python3.3/concurrent/futures/_base.py", line 193, in as_completed 
    with _AcquireFutures(fs): 
    File "...python3.3/concurrent/futures/_base.py", line 142, in __init__ 
    self.futures = sorted(futures, key=id) 
    File "...python3.3/concurrent/futures/_base.py", line 546, in result_iterator 
    yield future.result() 
    File "...python3.3/concurrent/futures/_base.py", line 392, in result 
    return self.__get_result() 
    File "...python3.3/concurrent/futures/_base.py", line 351, in __get_result 
    raise self._exception 
    File "...python3.3/concurrent/futures/thread.py", line 54, in run 
    result = self.fn(*self.args, **self.kwargs) 
    File "...futures_exceptions.py", line 7, in div_zero 
    return x/0 
ZeroDivisionError: division by zero 
+0

यह पूरी तरह से अस्थायी रूप से करने के लिए एक फोन के साथ 'pool.map' करने के लिए कॉल की जगह है समस्या है लेकिन एक चाल मैं अक्सर इन समस्याओं को दूर करने में इस्तेमाल किया है समाधान नहीं करता है: यह अन्य प्रश्न के मेरा उत्तर चेकआउट बिल्टिन 'मानचित्र'। –

उत्तर

3

मैं व्यक्तिगत रूप से Futures का उपयोग करता हूं क्योंकि इंटरफ़ेस बहुत आसान है। ट्रेसबैक मुद्दे के लिए मुझे इसे संरक्षित करने के लिए एक समाधान मिला।

Getting original line number for exception in concurrent.futures

0

आसान समाधान: उपयोग जो भी विकल्प सूट आप सबसे अच्छा है, और अपने कार्यकर्ताओं में अपने स्वयं के try-except ब्लॉक को लागू। यदि आपको जरूरी है तो रूट कॉल के आस-पास।

मैं नहीं कहूंगा कि ये पुस्तकालय अपवादों को "गलत तरीके से" संभालते हैं। उनके पास एक डिफ़ॉल्ट व्यवहार है, हालांकि आदिम। यदि आप डिफ़ॉल्ट रूप से उपयुक्त नहीं हैं तो आपको खुद को संभालने की उम्मीद है।

+0

'try-execpt' ब्लॉक जोड़ना किसी भी समस्या का समाधान नहीं कर सकता है। 'समवर्ती' के मामले में, मैं अभी भी नए अपवाद को पकड़ने के बाद मूल ट्रेसबैक नहीं कर सकता। 'वर्कपूल' के मामले में, मैं कभी भी ब्लॉक को छोड़कर नहीं जाता क्योंकि दुभाषिया पहले दुर्घटनाग्रस्त हो जाता है। 'थ्रेडपूल' के मामले में मैं कभी भी ब्लॉक को छोड़कर नहीं जाता क्योंकि कोई अपवाद नहीं उठाया जाता है। – xApple

+1

आप मुख्य धागे या प्रक्रिया में 'try' block' के बारे में सोच रहे हैं। मैं कह रहा हूं कि आप फंक्शन वर्कर प्रक्रियाओं के चारों ओर एक 'try' ब्लॉक का उपयोग करें। यदि आप किसी कार्यकर्ता थ्रेड/प्रक्रिया में अपवाद को बढ़ाने के लिए उम्मीद करते हैं और इसे अपनी मुख्य स्क्रिप्ट में भेज दिया है, तो आपको इसे पहले पकड़ने की आवश्यकता है। – slezica

+0

वैसे मैं उन कार्यों में से प्रत्येक के लिए त्रुटि प्रबंधन लिखने वाला नहीं हूं जिसे मैं चलाने के लिए चाहता हूं। तो आप जो कह रहे हैं वह है कि मुझे अपना खुद का वैश्विक त्रुटि प्रबंधन लिखना चाहिए। हां, मैं सिर्फ पुस्तकालयों में से एक चुन सकता था और कार्यक्षमता जोड़ने के लिए स्रोत कोड को संपादित करना शुरू कर सकता था, लेकिन यही वह है जो मैं टालना चाहता था:) – xApple

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