2013-10-29 7 views
6

में बवंडर async कोड मुझे लगता है कि मैं सामान्य रूप से एक बवंडर-आधारित वेब आवेदन के हिस्से के रूप में उपयोग tornado gen.coroutine का उपयोग कर कुछ अतुल्यकालिक कार्य हैं। हालांकि, मैं कुछ प्रशासन कार्यों को करने के लिए उनमें से कुछ को एक पुरानी पुरानी पायथन लिपि से कॉल करना चाहता हूं। मैं यह कैसे करु?उपयोग एक नियमित रूप से अजगर स्क्रिप्ट

from tornado import gen 

import some_internal_stuff 

@gen.coroutine 
def myfunc(x): 
    y = yield some_internal_stuff.another_async_func(x) 
    raise gen.Return(y) 

if __name__ == "__main__": 
    # What do I put here to call myfunc(1) and get the async return value? 
    pass 

अद्यतन:

एक और अधिक ठोस उदाहरण:

from tornado import gen 

@gen.coroutine 
def another_async_func(x): 
    print "aaf" 
    raise gen.Return(x + 1) 

@gen.coroutine 
def myfunc(x): 
    print "myfunc" 
    y = yield another_async_func(x) 
    print "back" 
    raise gen.Return(y) 

def callback(y): 
    print "Callback called with %d" % y 

if __name__ == "__main__": 
    myfunc(1, callback=callback) 

चल रहा है इस आउटपुट:

myfunc 
aaf 
+1

इस तरह के एक स्पष्ट सवाल पूछने के लिए क्षमा करें, लेकिन क्या आप some_internal_stuff.another_async_func कॉल करने से रोकता है (एक्स) सीधे और परिणाम की प्रतीक्षा कर रहे हैं? क्या आपके द्वारा बुलाए जाने वाले फ़ंक्शन में टोरनाडो पर निर्भरताएं हैं जो इसे रोकती हैं? –

+0

@rod: विचार यह है कि 'another_async_func' एक और तूफान' @ एसिंक्रोनस 'विधि है जो आमतौर पर एक बवंडर 'IOLoop' की उपस्थिति में चलता है। मैं 'another_async_func' चला सकता हूं और इसे 'कॉलबैक' पास कर सकता हूं, लेकिन बिना टर्ननाडो के चलने के बाद, 'myfunc' में उपज के बाद की रेखा कभी नहीं चलती है, और मैंने जो कॉलबैक पारित किया है उसे कॉल नहीं किया जाता है। – rakslice

उत्तर

16

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

from tornado import gen, ioloop 

@gen.coroutine 
def another_async_func(x): 
    print "aaf" 
    raise gen.Return(x + 1) 

@gen.coroutine 
def myfunc(x): 
    print "myfunc" 
    y = yield another_async_func(x) 
    print "back" 
    raise gen.Return(y) 

@gen.coroutine 
def main(): 
    y = yield myfunc(1) 
    print "Callback called with %d" % y 

if __name__ == "__main__": 
    ioloop.IOLoop.instance().run_sync(main) 

यह आउटपुट:

ठोस उदाहरण के साथ

myfunc 
aaf 
back 
Callback called with 2 

ध्यान दें कि run_sync घोंसला अच्छी तरह से नहीं करता है, यदि आप एक समारोह में एक ही IOLoop पर run_sync से बुलाया में run_sync फोन भीतरी कॉल के पूरा होने IOLoop बंद हो जाएगा और मन की कॉल के बाद आगे कोई yield रों वापस आ जाएगी।

1

यहाँ एक और संभावना, धागे का उपयोग कर, कि समस्या की जटिलता और अपनी आवश्यकताओं पर निर्भर करता है काम करेगा है:

if __name__ == "__main__": 
    import threading, time 
    # The tornado IO loop doesn't need to be started in the main thread 
    # so let's start it in another thread: 
    t = threading.Thread(target=IOLoop.instance().start) 
    t.daemon = True 
    t.start() 

    myfunc(1, callback=callback) 
    # now the main loop needs wait; you can do that by polling a value, sleeping, 
    # or waiting on a lock. I've chosen to sleep here, but a lock is probably more 
    # appropriate; and, once computation is done, release the lock. 
    time.sleep(2) 
संबंधित मुद्दे