मैंने किंडल के जवाब को चुरा लिया और इसे थोड़ा साफ कर दिया।
टाइमआउट को संभालने के लिए इसमें () और शामिल होने के लिए (*) को जोड़ने के लिए मुख्य भाग * आर्ग और ** क्वार्ग्स जोड़ रहा है
class threadWithReturn(Thread):
def __init__(self, *args, **kwargs):
super(threadWithReturn, self).__init__(*args, **kwargs)
self._return = None
def run(self):
if self._Thread__target is not None:
self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)
def join(self, *args, **kwargs):
super(threadWithReturn, self).join(*args, **kwargs)
return self._return
अद्यतन उत्तर पूर्व
यह मेरा सबसे लोकप्रिय उत्कीर्ण उत्तर है, इसलिए मैंने कोड के साथ अद्यतन करने का निर्णय लिया जो py2 और py3 दोनों पर चलेगा।
इसके अतिरिक्त, मुझे इस प्रश्न के कई उत्तर दिखाई देते हैं जो थ्रेड.जॉइन () के बारे में समझ की कमी दर्शाते हैं। कुछ पूरी तरह से timeout
आर्गन को संभालने में विफल रहते हैं । लेकिन एक कोने-मामला यह भी है कि आपको ऐसे उदाहरणों के बारे में पता होना चाहिए जब आपके पास (1) एक लक्ष्य फ़ंक्शन होता है जो वापस आ सकता है None
और (2) आप भी timeout
शामिल होने के लिए आर्ग पास करते हैं ()। कृपया इस कोने के मामले को समझने के लिए "TEST 4" देखें।
थ्रेडविथर्न क्लास जो py2 और py3 के साथ काम करता है:
import sys
from threading import Thread
from builtins import super # https://stackoverflow.com/a/30159479
if sys.version_info >= (3, 0):
_thread_target_key = '_target'
_thread_args_key = '_args'
_thread_kwargs_key = '_kwargs'
else:
_thread_target_key = '_Thread__target'
_thread_args_key = '_Thread__args'
_thread_kwargs_key = '_Thread__kwargs'
class ThreadWithReturn(Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._return = None
def run(self):
target = getattr(self, _thread_target_key)
if not target is None:
self._return = target(
*getattr(self, _thread_args_key),
**getattr(self, _thread_kwargs_key)
)
def join(self, *args, **kwargs):
super().join(*args, **kwargs)
return self._return
कुछ नमूने परीक्षण नीचे दिखाए गए हैं:
import time, random
# TEST TARGET FUNCTION
def giveMe(arg, seconds=None):
if not seconds is None:
time.sleep(seconds)
return arg
# TEST 1
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',))
my_thread.start()
returned = my_thread.join()
# (returned == 'stringy')
# TEST 2
my_thread = ThreadWithReturn(target=giveMe, args=(None,))
my_thread.start()
returned = my_thread.join()
# (returned is None)
# TEST 3
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=2)
# (returned is None) # because join() timed out before giveMe() finished
# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))
क्या आप उस कोने-मामले की पहचान कर सकते हैं जिसका सामना संभवतः TEST 4 से हो सकता है?
समस्या यह है कि हम उम्मीद करते हैं कि कोई भी रिटर्न (TEST 2 देखें) नहीं दे सकता, लेकिन हम यह भी उम्मीद करते हैं कि अगर इसमें से कोई भी वापस लौटता है तो वह इसमें शामिल हो जाए।
returned is None
या तो इसका मतलब है:
(1) यह है कि क्या दे () लौटे, या
(२) जुड़ना () समय समाप्त होना
यह उदाहरण तुच्छ है क्योंकि हम जानते हैं कि GiveMe () हमेशा कोई नहीं लौटेगा। लेकिन वास्तविक दुनिया में उदाहरण (जहां लक्ष्य वैध रूप से कोई भी या कुछ और नहीं लौटा सकता है) हम स्पष्ट रूप से जांचना चाहते हैं कि क्या हुआ।
नीचे इस कोने-मामले को संबोधित करने का तरीका बताया गया है:
# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))
if my_thread.isAlive():
# returned is None because join() timed out
# this also means that giveMe() is still running in the background
pass
# handle this based on your app's logic
else:
# join() is finished, and so is giveMe()
# BUT we could also be in a race condition, so we need to update returned, just in case
returned = my_thread.join()
futures = [executor.submit(foo, param) for param in param_list]
आदेश बनाए रखा जाएगा, औरwith
वसीयत से बाहर निकलने के परिणाम संग्रह की अनुमति देगा।[f.result() for f in futures]