Issue
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()
Solution
If you want to use asyncio
only:
Make this preparation once, it is quite low-level (set LIMIT e.g. 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 (e.g. GNU-readline style) input line in an asyncio task?
Answered By - VPfB
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.