使用Python进行动态终端打印
有些应用程序,比如 hellanzb,可以在终端上显示数据,看起来就像是动态更新一样,类似于 top() 命令的效果。
在 Python 中,做这个的最佳方法是什么呢?我了解了一些关于日志记录和 curses 的内容,但不太确定该用哪个。我正在重新实现 top 命令。如果你有其他建议,我也很乐意听听。
7 个回答
通过使用print()命令将输出发送到终端时,可以使用“end”这个属性来避免滚动。
默认情况下,end='\n'表示换行。
如果你想要避免滚动并覆盖整行之前的内容,可以使用RETURN转义字符'\r'。
如果你只想重写最后四个字符,可以使用几个退格。
print(value, "_of_", total, end='\r')
注意 这个方法适用于标准系统终端。但在一些工具的终端模拟器中,比如IDLE,'\r'可能会出现问题,输出会和一些不可打印的字符连接在一起。
关于print()的额外信息 在上面的例子中,“of”两边的空格是为了确保我的值和“of”之间有空白。不过,print()的默认分隔符是一个空格,所以最终在值和“_of_”之间会有空白。
>> print (value, "_of_", total, end='\r')
8 _of_ 17
分隔符属性sep可以用来设置打印项目之间的字符。在我的例子中,我会把它改成一个空字符串(''),这样我的输出就符合我的需求了。
>> print (value, "_of_", total, sep='', end='\r')
8_of_17
正如大多数回答所说,在Linux上你几乎只能使用ncurses
。但是,如果你不在Linux上,或者想要一些更高级的东西来创建终端界面呢?
我个人觉得在Python中缺少一个现代的、跨平台的终端API很让人失望,所以我写了asciimatics来解决这个问题。这个库不仅提供了一个简单的跨平台API,还提供了很多更高级的抽象功能,比如用户界面组件和动画,这些都可以轻松用来创建类似于top的界面。
如果你只需要更新一行内容,比如说制作一个进度条,最简单的方法就是使用 '\r'
(回车符)和 sys.stdout
:
import sys
import time
for i in range(10):
sys.stdout.write("\r{0}>".format("="*i))
sys.stdout.flush()
time.sleep(0.5)
如果你想要一个更完整的控制台界面,能够支持移动光标等功能,可以使用标准库中的 curses
模块:
import time
import curses
def pbar(window):
for i in range(10):
window.addstr(10, 10, "[" + ("=" * i) + ">" + (" " * (10 - i )) + "]")
window.refresh()
time.sleep(0.5)
curses.wrapper(pbar)
强烈建议使用 curses.wrapper
函数来调用你的主函数,这样可以在出错时自动清理终端,避免终端变得无法使用。
如果你要创建一个更复杂的界面,可以为屏幕的不同部分创建多个窗口,添加文本输入框和鼠标支持。