简体   繁体   中英

Implementation difficulties with aioconsole in an asyncio chat client | input() is not compatible with asyncio

I am coding a command line/shell chat. To better handle input and ouput I use asyncio. But asyncio doesn't work with python's standard input() function. So I have been looking for other solutions and came across aioconsole. But the documentation is quite hard to understand (and imho not that well written.) So could you please help me implement an asyncronous input in the function message_sender() by replacing the current placeholder function called asynchronous_input() . (A function without aioconsole would also work, it's just what I came across) And yes, there are other SO posts about similar things, but they all use very old asynio versions.

import asyncio
import struct

async def chat_client():
    reader, writer = await asyncio.open_connection("xxx.xxx.xxx.xxx", xxx)
    await message_sender(writer)
    await message_reciever(reader)

async def message_sender(writer):
    try:
        while True:
            message = await #asynchronous_input()
            await message_writer(message, writer)
    except asyncio.TimeoutError: # Just ignore this exception handler for now, it's only there for later
        print("----------- You lost your connection -----------")
        writer.close()
        await writer.wait_closed()
        quit()

async def message_reciever(reader):
        while True:
            size, = struct.unpack('<L', await reader.readexactly(4)) 
            rcv_message = await reader.readexactly(size)
            print(rcv_message.decode())

async def message_writer(message, writer):
        data = message.encode()
        writer.write(struct.pack('<L', len(data)))
        writer.write(data)
        await writer.drain()

try:
    message = ""
    asyncio.run(chat_client())
except KeyboardInterrupt:
    print("----------- You left the Chat. -----------")
    quit()

If you want to use asyncio only:

Make this preparation once, it is quite low-level (set LIMIT eg to 8192 (8K buffer)):

loop = asyncio.get_running_loop()
rstream = asyncio.StreamReader(limit=LIMIT, loop=loop)
protocol = asyncio.StreamReaderProtocol(rstream, loop=loop)
await loop.connect_read_pipe(lambda: protocol, sys.stdin)

and then, when you want to read a line asynchronously:

line = (await rstream.readline()).decode()

You'll get a text line with the newline included or an empty string on EOF.

However, it was only yesterday I posted a related question that it has really very limitied editing features. You might want to read it, a specialized library was recommended there: How to have a comfortable (eg GNU-readline style) input line in an asyncio task?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM