huhyuh
huhyuh

Reputation: 15

Python asyncio issues

I tested the following code with Ncat. It only sends a single message, then it does not send anything, and does not except. It is also not reading anything.

I have no idea what could be going on. There is no exception, and no data seems to be sent.

import asyncio


loop = asyncio.get_event_loop()

class Client:

    def __init__(self):
        self.writer = None
        self.reader = None

    async def connect(self, address, port):
        reader, writer = await asyncio.open_connection(address, port)
        self.reader = reader
        self.writer = writer
        print("connected!")

    async def send(self, message):
        print("writing " + message)
        self.writer.write((message + '\n').encode())
        await self.writer.drain()

    async def receive(self):
        print("receiving")
        message = (self.reader.readuntil('\n'.encode())).decode()
        return message

    async def read_loop(self):
        while True:
            incoming = await self.receive()
            print("remote: " + incoming)


async def main():
    client = Client()
    await client.connect("127.0.0.1", 31416)

    loop.create_task(client.read_loop())

    while True:
        text = input("message: ")
        await client.send(text)


loop.run_until_complete(main())

Upvotes: 0

Views: 480

Answers (1)

Andrea Tedeschi
Andrea Tedeschi

Reputation: 43

I haven't tested your code but there are things that immediately jump out.

First, you should avoid to use low-level asyncio APIs calling loop.create_task or loop.run_until_complete. Those are intended to be used by frameworks developers. Use asyncio.create_task and asyncio.run instead.

Then, you are getting no exception (or result) because you are not keeping any reference to the task you are creating. You should always keep one to tasks (i.e. assigning it to a variabile or adding it in a list/set).

Last, you are missing an await in the receive method: StreamReader.readuntil is a coroutine function and so you have to await on it.

class Client:
    ...
    async def receive(self):
        print('receiving...')
        message = await self.reader.readuntil('\n'.encode())
        return message.decode()
    ...

Upvotes: 1

Related Questions