如何实现一个很好地处理异步输出的python REPL?

时间:2009-01-12 21:11:44

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

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

问题是有异步事件进入,我想尽快打印输出。不幸的是,这让事情看起来很难看。输出后,“>”字符串不再显示,如果用户输入内容的一半,则会将文本切成两半。它可能应该在打印之后重新绘制用户正在进行的文本。

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

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

TIA

编辑:接受的答案适用于Unixy平台(当readline模块可用时),但是如果有人知道如何在Windows下完成这项工作,那将非常感谢!

6 个答案:

答案 0 :(得分:8)

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

#!/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()

我认为stdin不是线程安全的,所以你最终可能会丢失中断线程中的字符(用户必须在interrupt的末尾重新输入)。我通过interrupt电话夸大了time.sleep时间。 <{1}}调用不会显示丢失的字符,所以一切都好了。

请注意,stdout本身不是线程安全的,所以如果你有多个执行中断线程,那么这仍然看起来很糟糕。

答案 1 :(得分:5)

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

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

答案 2 :(得分:2)

运行这个:

python -m twisted.conch.stdio

你会得到一个漂亮的彩色异步REPL,而不使用线程。键入提示时,事件循环正在运行。

答案 3 :(得分:0)

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

答案 4 :(得分:-1)

这是一种非答案,但我会查看IPython的代码,看看他们是如何做的。

答案 5 :(得分:-1)

我认为你有两个基本选择:

  1. 同步您的输出(即阻止它返回)
  2. 将输入和(异步)输出分开,可能分为两列。