python - In a no-coroutine function, how do you get a return value from coroutine function of Tornado TCP? -
i wrote 3 sections of code tornado tcp. i've encountered difficulties.
my code following:
client.py
'''tcp client''' socket import socket, af_inet, sock_stream s = socket(af_inet, sock_stream) s.connect(('localhost', 20000)) resp = s.recv(8192) print('response:', resp) s.send(b'hello\n') s.close()
server.py
'''tcp server''' #! /usr/bin/env python #coding=utf-8 tornado.tcpserver import tcpserver tornado.ioloop import ioloop tornado.gen import * clientdict=dict() #save infomation of client class tcpconnection(object): def __init__(self,stream,address): self._stream=stream self._address=address self._stream.set_close_callback(self.on_close) @coroutine def send_messages(self): yield self.send_message(b'world \n') response = yield self.read_message() return response def read_message(self): return self._stream.read_until(b'\n') def send_message(self,data): return self._stream.write(data) def on_close(self): global clientdict clientdict.pop(self._address) print("the monitored %d has left",self._address) class monitorserver(tcpserver): @coroutine def handle_stream(self,stream,address): global clientdict print("new connection",address,stream) clientdict.setdefault(address, tcpconnection(stream,address)) if __name__=='__main__': print('server start .....') server=monitorserver() server.listen(20000) ioloop.instance().start()
main.py
import time threading import thread import copy server import * def watchclient(): '''call "send" function when new client connect'' global clientdict print('start watch') lastclientlist=list() while true: currentclientlist=copy.deepcopy([key key in clientdict.keys()]) difference=list(set(currentclientlist).difference(set(lastclientlist))) if len(difference)>0: send(difference) lastclientlist=copy.deepcopy(currentclientlist) time.sleep(5) else: time.sleep(5) continue def send(addresslist): '''send message new client , response''' global clientdict address in addresslist: response=clientdict[address].send_messages() print(address," response :",response) def listen(): server=monitorserver() server.listen(20000) ioloop.instance().start() if __name__=='__main__': listenthread=thread(target=listen) watchthead=thread(target=watchclient) watchthead.start() listenthread.start()
i want "print information" when main.py run---address,response:b'hello\n'
but in fact "print information" ----
('127.0.0.1', 41233) response :<tornado.concurrent.future object @ 0x7f2894d30518>
it can't return b'hello\n'.
then guess can't response reasonably in no-coroutine function(def send(addresslist)) coroutine function( @coroutine def send_messages(self)).
how solve this?
by way, want know how make clientdict property of class monitorserver,not global property. please me! thank you.
in general, calls coroutine should coroutine itself. mixing threads , coroutines can tricky; coroutine-based code deliberately not thread-safe.
the correct way call coroutine non-coroutine function on different thread this:
def call_coro_from_thread(f, *args, **kwargs): q = queue.queue() def wrapper(): fut = f(*args, **kwargs) fut.add_done_callback(q.put) ioloop.instance().add_callback(wrapper) fut = q.get() return fut.result()
ioloop.add_callback
necessary safely transfer control ioloop thread, , queue used transfer result back.
Comments
Post a Comment