【问题标题】:How to implement a python REPL that nicely handles asynchronous output?如何实现一个很好地处理异步输出的python REPL?
【发布时间】:2009-01-12 21:11:44
【问题描述】:

我有一个基于 Python 的应用程序,它可以在一个简单的 read-eval-print-loop 中接受一些命令。我正在使用raw_input('> ') 来获取输入。在基于 Unix 的系统上,我还 import readline 让事情表现得更好一些。这一切都很好。

问题是有异步事件进入,我想在它们发生时立即打印输出。不幸的是,这让事情看起来很难看。 "> " 字符串在输出后不会再次出现,如果用户正在输入一半内容,它会将他们的文本切成两半。它可能应该在打印某些内容后重绘用户正在处理的文本。

这似乎是一个已解决的问题。这样做的正确方法是什么?

另请注意,我的一些用户是基于 Windows 的。

TIA

编辑:接受的答案在 Unixy 平台下有效(当 readline 模块可用时),但如果有人知道如何在 Windows 下使其工作,将不胜感激!

【问题讨论】:

    标签: python readline read-eval-print-loop


    【解决方案1】:

    也许这样的事情可以解决问题:

    #!/usr/bin/env python2.6
    
    from __future__ import print_function
    
    import readline
    import threading
    
    PROMPT = '> '
    
    def interrupt():
        print() # Don't want to end up on the same line the user is typing on.
        print('Interrupting cow -- moo!')
        print(PROMPT, readline.get_line_buffer(), sep='', end='')
    
    def cli():
        while True:
            cli = str(raw_input(PROMPT))
    
    if __name__ == '__main__':
        threading.Thread(target=cli).start()
        threading.Timer(2, interrupt).start()
    

    我不认为标准输入是线程安全的,因此您最终可能会将字符丢失给中断线程(用户必须在interrupt 的末尾重新键入)。我用time.sleep 电话夸大了interrupt 的时间。 readline.get_line_buffer 调用不会显示丢失的字符,所以一切正常。

    请注意,stdout 本身不是线程安全的,因此,如果您有多个执行中断线程,这仍然会看起来很糟糕。

    【讨论】:

    • 谢谢,readline.get_line_buffer() 是一个好的开始。如果有人对在 Windows(没有 readline 模块)中进行这项工作有任何提示,请告诉我。
    • 这仍然是 2021 年的方式,还是非常接近的方式?有什么我应该知道的已经改变了吗?我正在使用 discord.py 制作一个不和谐的机器人,并且遇到了与提问者相同的问题。我使用 aioconsole 获得了非阻塞输入,但如果没有不同的输入/输出源以视觉上令人不快的方式相互交错,我似乎无法获得它
    【解决方案2】:

    为什么要使用 raw_input() 编写自己的 REPL?你看过cmd.Cmd 类吗? 编辑:我刚刚找到了sclapp 库,它可能也很有用。

    注意:cmd.Cmd 类(和 sclapp)可能会也可能不会直接支持您的原始目标;您可能必须对其进行子类化并根据需要对其进行修改以提供该功能。

    【讨论】:

    • cmd.Cmd 看起来非常棒,我应该开始使用它了。但是,它似乎并没有实现我最初的目标,有什么提示吗?
    • sclapp 似乎已不复存在。提供的链接失效了,我也没有找到它的新家。
    【解决方案3】:

    运行这个:

    python -m twisted.conch.stdio
    

    您将获得一个漂亮的、彩色的、异步的 REPL,不使用线程。当您输入提示时,事件循环正在运行。

    【讨论】:

      【解决方案4】:

      查看代码模块,它还允许您创建用于解释 python 代码的对象(无耻插件)https://github.com/iridium172/PyTerm 允许您创建处理原始键盘输入的交互式命令行程序(如 ^C 将引发 KeyboardInterrupt)。

      【讨论】:

        【解决方案5】:

        这是一个没有答案的问题,但我会查看IPython 的代码,看看他们是如何做到的。

        【讨论】:

          【解决方案6】:

          我认为您有 2 个基本选择:

          1. 同步您的输出(即阻塞直到它返回)
          2. 将输入和(异步)输出分开,可能在两个单独的列中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-07-15
            • 1970-01-01
            • 2022-06-30
            • 2017-02-07
            • 2012-02-06
            • 2013-05-10
            • 2013-07-10
            • 1970-01-01
            相关资源
            最近更新 更多