2010-09-10 19 views
8

के बीच अंतर defer.execute() और threads.deferToThread() के बीच क्या अंतर है? दोनों एक ही तर्क लेते हैं - एक फ़ंक्शन, और पैरामीटर इसे कॉल करने के लिए - और एक स्थगित लौटाएं जो फ़ंक्शन को कॉल करने के परिणामस्वरूप निकाल दिया जाएगा।मुड़: 'defer.execute` और `threads.deferToThread`

threads संस्करण स्पष्ट रूप से बताता है कि यह एक थ्रेड में चलाया जाएगा। हालांकि, अगर defer संस्करण नहीं है, तो इसे कॉल करने का क्या मतलब होगा? रिएक्टर में चलने वाले कोड को कभी भी अवरुद्ध नहीं करना चाहिए, इसलिए किसी भी फंक्शन को कॉल करना नहीं होगा। उस बिंदु पर, आप उसी परिणाम के साथ defer.execute(f, args, kwargs) के बजाय defer.succeed(f(*args, **kwargs)) कर सकते हैं।

उत्तर

9

defer.execute वास्तव में एक अवरुद्ध ढंग से फ़ंक्शन निष्पादित करता है, एक ही धागे में और आप सही में है कि defer.execute(f, args, kwargs) कि defer.execute एक कॉलबैक कि errback पड़ा है अगर समारोह निकाल वापस आ जाएगी छोड़कर defer.succeed(f(*args, **kwargs))के रूप में ही करता हैं एफ एक अपवाद फेंकता है। इस बीच, आपके defer.succeed उदाहरण में, अगर समारोह एक अपवाद फेंक दिया, यह बाहर फैल जाएगा, जो वांछित नहीं हो सकता है।

समझ की आसानी के लिए, मैं सिर्फ defer.execute के स्रोत यहाँ पेस्ट करना होगा:

def execute(callable, *args, **kw): 
    """Create a deferred from a callable and arguments. 

    Call the given function with the given arguments. Return a deferred which 
    has been fired with its callback as the result of that invocation or its 
    errback with a Failure for the exception thrown. 
    """ 
    try: 
     result = callable(*args, **kw) 
    except: 
     return fail() 
    else: 
     return succeed(result) 

दूसरे शब्दों में, defer.execute के रूप में एक आस्थगित एक अवरुद्ध समारोह के परिणाम लेने के लिए सिर्फ एक शॉर्टकट है जो आप कर सकते हैं फिर कॉलबैक/गलती जोड़ें। कॉलबैक सामान्य चेनिंग अर्थशास्त्र के साथ निकाल दिया जाएगा। यह थोड़ा पागल लगता है, लेकिन कॉलबैक जोड़ने से पहले डिफर्रेड 'आग' कर सकते हैं और कॉलबैक अभी भी कॉल किए जाएंगे।


तो अपने सवाल का जवाब देने, क्यों यह उपयोगी है? खैर, defer.execute दोनों परीक्षण/मॉकिंग के साथ-साथ सिंक्रोनस कोड के साथ एसिंक एपीआई को एकीकृत करने के लिए उपयोगी है।

भी उपयोगी है defer.maybeDeferred जो फ़ंक्शन को कॉल करता है और फिर यदि फ़ंक्शन पहले से ही स्थगित लौटाता है तो इसे वापस लौटाता है, अन्यथा defer.execute के समान कार्य करता है। यह तब उपयोगी होता है जब आप एक एपीआई लिखते हैं जो कॉल करने योग्य से अपेक्षा करता है कि जब आपको बुलाया जाता है तो आपको स्थगित कर दिया जाता है, और आप सामान्य अवरोधन कार्यों को भी स्वीकार करने में सक्षम होना चाहते हैं।

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

from twisted.internet import defer 
from twisted.web.client import getPage 

def process_feed(url, getter=getPage): 
    d = defer.maybeDeferred(getter, url) 
    d.addCallback(_process_feed) 

def _process_feed(result): 
    pass # do something with result here 

एक तुल्यकालिक संदर्भ में इस चलाने के लिए, रिएक्टर के बिना, तो आप सिर्फ एक वैकल्पिक गेटर समारोह गुजर सकता है, इसलिए जैसे:

from urllib2 import urlopen 

def synchronous_getter(url): 
    resp = urlopen(url) 
    result = resp.read() 
    resp.close() 
    return result 
+0

+ Defer.maybe व्याख्या करने के लिए 1 –

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