Reputation: 10025
Disclaimer: This is probably a very basic question, but I just don't understand the concept and am thus unable to achieve what I want.
I'm trying to implement the basic echo client server using asyncio. I started with the samples included in the documentation.
What I want to achieve is a persistent connection where the client can at any time other than immediate connection_made send some data to the server and then read the response (if there is any). The connection must stay open on both ends until explicitly closed.
I'm doing this with protocols sample. Reading other questions / documentation, it seems I could implement this using loop.call_later()
, but is this really a good solution? Ideally I'd want to use a Queue
to be able to respond to new packets instantaneously.
I ended up with this code, called from ´MyProtocol.init`:
@asyncio.coroutine
def writer():
global out_queue
while True:
packt = yield from out_queue.get()
print("yeahhh packet yummy")
data = bytes(packt.to_json(), 'ascii')
self.transport.write(data)
asyncio.async(writer())
But this does nothing. I would assume that this would print out the message immediately when a new item is inserted from main client code. Nothing happens...
Further debugging shows that queue is being filled up, but the out_queue.get() coroutine never returns. Initially the out_queue.put even puts the item pretty much directly into the waiter for the initial .get() call, but it's as if the loop wasn't running. It's the same loop used for the entire client connection (i created a new one because I placed everything into a thread). I have checked and the appropriate calls made from .put() call are all for this loop.
Oh, just in case it matters: I'm running this on python 3.3 with asyncio install by pip.
Update: this is how I try to insert items into the queue:
def send_packet(loop, queue, packet):
# this runs in main thread, not the loop thread
def f():
print("putting packet into queue")
queue.put_nowait(packet) # MUST NOT use .put() as it's a coroutine
loop.call_soon_threadsafe(f)
# !!! next one doesn't work !!!
# loop.call_soon_threadsafe(any_normal_function_with_coroutine_calls())
The print
never executes.
Upvotes: 1
Views: 1859
Reputation: 17366
The only reason why queue.get() never wakes up after queue.put() is: you create queue with implicit loop (and maybe wait for items from this loop) but push data using another loop instance.
Upvotes: 1