2016-02-21 8 views
10

इस छोटे से टुकड़ा पर विचार करें:पाइथन 3.5 स्टाइल एसिंक का उपयोग कैसे करें और वेबकॉकेट्स के लिए टोरनाडो में प्रतीक्षा करें?

import tornado 
import tornado.websocket 
import tornado.ioloop 
import tornado.gen 
import tornado.web 

class NewWsHandler(tornado.websocket.WebSocketHandler): 
    async def on_message(self, message): 
     await self.write_message("echo " + message) 

class OldWsHandler(tornado.websocket.WebSocketHandler): 
    @tornado.gen.coroutine 
    def on_message(self, message): 
     yield self.write_message("echo " + message) 

app = tornado.web.Application([(r'/', OldWsHandler)]) 
app.listen(8080) 
tornado.ioloop.IOLoop.current().start() 

OldWsHandler तूफान में अतुल्यकालिक कार्यों करने का पूर्व 3.5 तरीका का उपयोग करता है, और यह ठीक काम करता है। हालांकि, as the documentation states, इसे पढ़ने योग्यता और गति के लिए PEP 0492 का उपयोग करना पसंद किया जाता है।

प्रलेखन कहते हैं:

सीधे शब्दों में yield के स्थान पर @gen.coroutine डेकोरेटर के साथ एक समारोह परिभाषा के स्थान पर async def foo(), और await का उपयोग करें।

इसलिए मैंने NewWsHandler लिखा था।

 
/usr/lib/python3.5/site-packages/tornado/websocket.py:417: RuntimeWarning: coroutine 'on_message' was never awaited 
    callback(*args, **kwargs) 

मैं सच में पता नहीं कैसे करने के लिए (ठीक से) इसे ठीक: हालांकि, जब एक WebSocket संदेश भेजने, यह एक चेतावनी उठाती है। मैंने tornado.web.asynchronous में इसे सजाने की कोशिश की, लेकिन यह HTTP verb method मानता है। तो बाद मैं ओवरराइड finish() (WebSockets ऐसा करने की अनुमति नहीं है), यह एक तरह से काम कर रहे हो रहा है:

class NewWsHandler(tornado.websocket.WebSocketHandler): 
    def finish(self): 
     pass 

    @tornado.web.asynchronous 
    async def on_message(self, message): 
     await self.write_message("echo " + message) 

लेकिन यह अभी भी hackerish लग रहा है, और प्रलेखन का खंडन किया जा रहा है। ऐसा करने का सही तरीका क्या है?

नोट: मैं पायथन 3.5.1 और टॉरनाडो 4.3 का उपयोग कर रहा हूं।

उत्तर

4

कोरआउट को नियमित कार्यों से अलग कहा जाता है; इसलिए जब उप-वर्गीकरण और ओवरराइडिंग विधियां आप बेस क्लास में अपने उप-वर्ग में कोरआउटिन में नियमित विधि नहीं बदल सकते हैं (जब तक कि बेस क्लास विशेष रूप से यह ठीक न कहें)। WebSocketHandler.on_message कोरआउट नहीं हो सकता है (टॉरनाडो 4.3 के रूप में; यह भविष्य में बदल सकता है)। इसके बजाए, अगर आपको किसी संदेश के जवाब में एसिंक्रोनस कुछ करने की ज़रूरत है, तो एसिंक्रोनस पार्ट्स को एक अलग फ़ंक्शन में रखें और इसे IOLoop.current().spawn_callback से कॉल करें। (या write_message एकमात्र एसिंक चीज है जो आप कर रहे हैं, बस इसे सिंक्रनाइज़ करें)

+0

क्या कोई तरीका है कि मैं किसी वेबसॉकेट संदेश के जवाब में डेटाबेस (असीमित रूप से) पूछ सकता हूं? कुछ 'परिणाम = प्रतीक्षा प्रश्न (...)' की तरह कुछ? मुझे ऐसा करने का वास्तविक अच्छा तरीका नहीं दिख रहा है। (मेरे प्रश्न में 'हैक्स' के अलावा)। – evertheylen

+1

एक बार जब आप एक अलग कॉलबैक तैयार कर लेते हैं तो आप जो भी चाहें कर सकते हैं। आपको अपवाद हैंडलिंग से सावधान रहना होगा क्योंकि यहां उठाए गए किसी भी अपवाद को 'on_message' से गुज़रना नहीं होगा और वेबसाइकिल कनेक्शन को प्रभावित करेगा। यह भी ध्यान रखें कि पिछले एक के समाप्त होने से पहले एक और संदेश आ सकता है; इससे बचने के लिए कि आप 'on_open()' में कॉलबैक बनाना चाहते हैं और कतार का उपयोग करके इसके साथ संवाद कर सकते हैं। –

+0

धन्यवाद! अब यह सब स्पष्ट है। – evertheylen

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