2012-07-22 6 views
14

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

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

मैंने पहले से ही बहु-प्रसंस्करण किया है और सबसे खराब मामला है कि मैं सिर्फ इस काम को करने के लिए थ्रेड फोर्क कर सकता हूं लेकिन यदि वापसी विवरण के बाद काम करने का कोई तरीका था तो यह आसान होगा।

उदाहरण:

def profile_update(inputs): 
    #take updates and update the database 
    return "it worked" 
    #do maintainence processing now.. 
+1

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

उत्तर

9

नहीं है, दुर्भाग्य से, एक बार आप return बयान मारा, तुम समारोह/विधि (या तो साथ या एक वापसी मान के बिना) से लौटने।

docs for return से

:

वापसी अभिव्यक्ति सूची (या कोई नहीं) वापसी मान के रूप में के साथ वर्तमान समारोह कॉल छोड़ देता है।

आप जनरेटर कार्य करता है और yield बयान में देखना चाहते हो सकता है, यह एक समारोह से मान और प्रसंस्करण और एक अन्य मूल्य की तैयारी जारी रखने के लिए वापस करने के लिए एक रास्ता जब समारोह अगली बार कहा जाता है ।

+0

रोचक, उपज के बारे में नहीं सोचा था .. मैंने सोचा था कि इसे फ़ंक्शन में एक मान वापस करने के लिए उपयोग किया जाता था जिसे इसे प्रतिक्रिया के रूप में नहीं कहा जाता था। असल में मैं एक शब्दकोश के रूप में एक http प्रतिक्रिया वापस कर रहा हूँ। मैं नहीं बदल सकता कि कैसे HTTPS रिटर्न स्वीकार करता है लेकिन मैं कुछ खुदाई करूँगा और देख सकता हूं कि क्या मैं उपज के साथ अपने आदेश को प्रतिस्थापित कर सकता हूं। दिलचस्प विचार, धन्यवाद। – Lostsoul

+0

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

+0

@ बेन लेकिन स्पष्ट रूप से कॉलर को इंगित करना होगा कि रखरखाव की सामग्री कब चलनी चाहिए, क्योंकि अगर हर बार ठीक है तो हम इसे लौटने से पहले ही चला सकते हैं। रिटर्न में कौन सा मतलब है कि हमें किसी भी तरह की दो कॉल की ज़रूरत है और यही वह है जो कोरआउट की जरूरत है। – Voo

13

आप contextmanager का उपयोग क्यों नहीं करते? यह मूल रूप से वही करता है जो आप चाहते हैं।

यहां पाइथन डॉक्स से कैननिकल उदाहरण है।

from contextlib import contextmanager 

@contextmanager 
def tag(name): 
    print "<%s>" % name 
    yield 
    print "</%s>" % name 
अपने समारोह के लिए

तो, तुम सिर्फ कर चाहते हैं:

@contextmanager 
def profile_update(inputs): 
    #take updates and update the database 
    yield "it worked" 
    #do maintainence processing now.. 

और यह कॉल करने के लिए, आप बस करना चाहते हैं:

with profile_update(inputs) as result: #pre-yield and yield here 
    # do whatever while in scope 
# as you move out of scope of with statement, post-yield is executed 

संपादित करें: मैं सिर्फ बातें परीक्षण किया गया था बाहर, और यह पता चला है कि, उपज बयान के साथ, समारोह अभी भी अंत तक निष्पादित करता है। यहां एक गूंगा उदाहरण है जो बिंदु को दिखाता है और जब चीजें निष्पादित होती हैं।

def some_generator(lst): 
    for elem in lst: 
     yield elem 
    lst[0] = "I WAS CHANGED POST-YIELD!!!!" 

>>> q = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> gen = some_generator(q) 
>>> for e in gen: 
... print e, q 

0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
5 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
6 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
7 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

print q 
['I WAS CHANGED POST YIELD!!!', 1, 2, 3, 4, 5, 6, 7, 8, 9] 

एक contextmanager रोक यात्रा (और क्लीनर वाक्य रचना) को पाने के लिए दो next कॉल की जरूरत नहीं का लाभ दिया है, लेकिन अगर आप एक से अधिक मान या कुछ और देखना चाहता है, तो आप इसे इस तरह से भी कर सकता है, लेकिन आप देख सकते हैं कि पोस्ट उपज बयान वास्तव में जब तक जनरेटर next फोन पर StopIteration उठाती नहीं कहा जाता हो जाता है (पाश के लिए समाप्त हो जाती है जब यह StopIteration हो जाता है)


किसी कारण से, आप एक उच्च डिग्री की आवश्यकता होती है @contextmanager से अधिक नियंत्रण के लिए, आप als कर सकते हैं ओ __enter__ और __exit__ तरीकों के साथ एक वर्ग को परिभाषित:

class MyContextClass(object): 
    # ... 

    def __enter__(self): 
     # do some preprocessing 
     return some_object 

    def __exit__(self, exc_type, exc_value, traceback): 
     # do some post processing 
     # possibly do some processing of exceptions raised within the block 
     if exc_type == MyCustomErrorType: 
      return True #don't propagate the error 
+0

@ जोएल कॉर्नेट, वहां अच्छा संपादन करें। यह एक अच्छा मुद्दा है कि 'संदर्भ प्रबंधक' एक और जटिल वर्ग के लिए सिंटैक्टिक चीनी है। –

+0

मुझे लगता है कि 'q' होना चाहिए [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]' '0, 1, 2, 3, 4]' आपके उदाहरण में –

+0

@ AlexandrPriymak हाँ, मैंने अपनी मशीन पर चलते समय इसे बदल दिया, मैं इसे ठीक कर दूंगा। –

6

तुम अब भी वापसी के बाद कुछ काम कर सकता है अगर आप एक कोशिश ब्लॉक से लौटने के लिए, अंत में ब्लॉक अभी भी निष्पादित किया जाएगा, जैसे:

def fun(): 
    try: 
     return 
    finally: 
     print "Yay! I still got executed, even though my function has already returned!" 

का हवाला देते हुए the docs:

जब वापसी एक अंत में +०१२३५१६४१०६ साथ एक कोशिश बयान से बाहर नियंत्रण गुजरताखंड, अंततः फ़ंक्शन को छोड़ने से पहले खंड को निष्पादित किया जाता है।

+5

लेकिन अंततः कॉलर को लौटाए गए मान प्राप्त करने से पहले * आखिरकार * चलाएगा। इससे आपको कॉलर को प्रतिक्रिया प्राप्त करने और उपयोगकर्ता को सूचित करने में मदद नहीं मिलती है, लेकिन * फिर * अधिक कोड चलाएं। – Ben

+2

उपयोग के मामले के आधार पर, यह ठीक हो सकता है। यह आपके फ़ंक्शन की सामग्री को प्रयास में लपेटने के लिए एक सुविधाजनक प्रवाह नियंत्रण तकनीक हो सकती है, और विभिन्न प्रकार के रिटर्न स्टेटमेंट्स हैं, जिनमें से सभी प्रवाह को सीधे रखरखाव करने के लिए अंत में ब्लॉक छोड़ देंगे। – andyortlieb

3

नहीं, एक रिटर्न कॉलर को वापस मूल्य देता है और बंद हो जाता है।

तो फोन करने वाले (रों) अपने नियंत्रण (पिरामिड ढांचे का हिस्सा नहीं) के तहत भी कर रहे हैं, तो आप profile_updates बदल निम्नलिखित की तरह लग रहे करने के लिए कर सकते हैं:

def profile_update(inputs): 
    #take updates and update the database 
    def post_processing_task(): 
     #do maintainence processing now.. 
    return ("it worked", post_processing_task) 

और फिर एक जोड़ी की उम्मीद फोन करने वाले कोड केवल एक प्रतिक्रिया के बजाय (response, task) का। यह response भाग (उपयोगकर्ता को इसे संवाद) के साथ तुरंत कुछ कर सकता है, फिर पोस्ट-प्रोसेसिंग को संभालने के लिए task() पर कॉल करें।

यह profile_update को यह निर्धारित करने के लिए profile_update की अनुमति देता है कि यह निर्धारित करने के लिए कि कौन से कोड को निष्पादित किया जाना चाहिए (और उन विवरणों को छुपाएं और उच्च स्तर से encapsulated रखें), लेकिन उच्च स्तर को उपयोगकर्ता को प्रतिक्रिया संचार करने के प्रवाह को निर्धारित करने और फिर निष्पादित करने की अनुमति देता है पृष्ठभूमि में पोस्ट प्रोसेसिंग।

+0

+1 ग्रेट विचार, मैं कुछ परीक्षण करूँगा लेकिन इस समस्या के बारे में सोचने का बहुत ही रोचक तरीका! – Lostsoul

+0

हू। मुझे नहीं पता था कि पाइथन ऐसा कर सकता है। बहुत धन्यवाद! –

-1

try-except-finally संरचना के साथ धोखा देना संभव है। उदाहरण:

def function(): 
    try: 
    #do some stuff here 
    return x 
    except Exception: 
    #do something when an error occures 
    finally: 
    #do here whatever you wanna do after return 

ध्यान दें, कि finally बयान भले ही एक अपवाद पकड़ा गया था निष्पादित किया जाएगा।

3
import threading 

def profile_update(inputs): 

    # call function to take updates and update the database 
    update_function(inputs) 

    # call the maintainence_function here 
    t = threading.Thread(target=maintainence_function, args=[input1, input2]) 
    # setDaemon=False to stop the thread after complete 
    t.setDaemon(False) 
    # starting the thread 
    t.start() 

    # return response/anything-else you want to return 
    return "it worked" 



def update_function(inputs): 
    # updating the database process here 

def maintainence_function(input1, input2): 
    #do maintainence processing now.. 

यहां हम अजगर की थ्रेडिंग कार्यक्षमता का उपयोग करते हैं।

सबसे पहले हम अपडेट फ़ंक्शन को कॉल करते हैं (यदि आवश्यक हो तो आप इस फ़ंक्शन को थ्रेड में भी उपयोग कर सकते हैं और यदि प्रतिक्रिया इस फ़ंक्शन पर निर्भर नहीं होती है और यदि आपको तुरंत प्रतिक्रिया देने की आवश्यकता है)।

फिर हमने एक धागा बनाया है जो रखरखाव_फंक्शन फ़ंक्शन को पूरा करेगा और इसे समाप्त करने के बाद रोक देगा। लेकिन उस कार्य को समाप्त होने तक प्रतिक्रिया में देरी नहीं होगी।

यानी: लौटाएं "यह काम किया गया" वापस लौटा दिया जाएगा और फिर थ्रेड थोड़ी सी प्रक्रिया में फंक्शन रखरखाव_फंक्शन के काम को बनाए रखेगा।

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