【问题标题】:Implementation difficulties with aioconsole in an asyncio chat client | input() is not compatible with asyncio在 asyncio 聊天客户端中使用 aioconsole 的实现困难 | input() 与 asyncio 不兼容
【发布时间】:2022-01-08 21:18:22
【问题描述】:

我正在编写命令行/shell 聊天。为了更好地处理输入和输出,我使用 asyncio。但是 asyncio 不适用于 python 的标准 input() 函数。所以我一直在寻找其他解决方案并遇到了 aioconsole。但是文档很难理解(恕我直言,写得不是很好。)所以请您帮我在函数message_sender() 中实现异步输入,方法是替换当前名为asynchronous_input() 的占位符函数。 (没有 aioconsole 的函数也可以工作,这正是我遇到的)是的,还有其他关于类似事情的 SO 帖子,但它们都使用非常旧的 asynio 版本。

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()

【问题讨论】:

    标签: python input chat python-asyncio


    【解决方案1】:

    如果您只想使用asyncio

    做一次这个准备,它是相当低级的(设置 LIMIT 例如到 8192(8K 缓冲区)):

    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)
    

    然后,当你想异步读取一行时:

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

    你会得到一个包含换行符的文本行或 EOF 上的一个空字符串。

    然而,就在昨天我发布了一个相关问题,它的编辑功能确实非常有限。您可能想阅读它,那里推荐一个专门的库:How to have a comfortable (e.g. GNU-readline style) input line in an asyncio task?

    【讨论】:

    • 感谢您的宝贵时间,但在实施您的建议后,它实际上并没有调用message_reciever(),而是卡在message_seder()
    • 或者更准确地说,无论我先调用哪个函数,所以message_sender()message_reciever另一个永远不会运行
    • @SoccerFan 当一个函数在await 中等待时,其他异步任务可以在这段时间内运行。但是你没有其他任务。如果你想独立运行发送者和接收者,你必须创建任务。有一个如何同时运行多个任务的例子:docs.python.org/3/library/…
    • 哦,是的,谢谢你的提醒,我混淆了一些术语
    • @SoccerFan 很高兴能帮上忙。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2021-09-30
    • 1970-01-01
    相关资源
    最近更新 更多