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

问题描述 投票:0回答:7

我有一个基于 Python 的应用程序,可以在简单的读取-评估-打印循环中接受一些命令。我正在使用

raw_input('> ')
来获取输入。在基于 Unix 的系统上,我还
import readline
让事情表现得更好一点。这一切都运行良好。

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

这看起来一定是一个已解决的问题。正确的方法是什么?

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

蒂亚

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

python readline read-eval-print-loop
7个回答
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
时间。
readline.get_line_buffer
调用不会显示丢失的字符,所以一切正常。

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


5
投票

你为什么使用

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

注意:

cmd.Cmd
类(和sclapp)可能会也可能不会直接支持你最初的目标;您可能需要对其进行子类化并根据需要进行修改才能提供该功能。


2
投票

运行这个:

python -m twisted.conch.stdio

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


0
投票

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


0
投票

其他一些方法:


-1
投票

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


-1
投票

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

  1. 同步你的输出(即阻塞直到它回来)
  2. 将输入和(异步)输出分开,也许在两个单独的列中。
© www.soinside.com 2019 - 2024. All rights reserved.