我有一些输出我想写一下,并且有一个简单的Python函数可以完成这个(在OS X上的终端)但我不确定我是否可以依赖它:
import sys
import time
def print_over(s):
print(s, end='\r')
print("\033[F" * (s.count('\n')+1))
sys.stdout.flush()
time.sleep(0.2)
我知道会有一些情况,当然这不会起作用,但是很奇怪
答案 0 :(得分:1)
忽略有关微软Console API(OP可以探索)的可移植性的讨论,并且只关注“ANSI-escapes”工作的地方:
这一行特别有意义,因为它是唯一使用的转义序列:
print("\033[F" * (s.count('\n')+1))
这对应于ECMA-48控件 CPL
,例如XTerm Control Sequences:
CSI Ps F Cursor Preceding Line Ps Times (default = 1) (CPL).
OP问“我有多广泛地期待它的运作”。这取决于。它在xterm中实现(而Terminal.app实现了相当大的一部分),但不是VT100或VT220的一部分(参见http://vt100.net的文档)。它被添加到1996的xterm中。所以考虑它仅限于模仿xterm的程序。
POSIX对此话题无话可说。 X/Open Curses(不属于POSIX)是关闭的 - 但CPL与任何terminfo功能都不对应。 ECMA-48是相关的,但无法保证ECMA-48中列出的任何功能在任何给定终端中实施。相反,它列举了可能性并规定了它们的语法。同样不能保证在另一个程序中找到xterm的任何给定功能(例如参见Comparing versions, by counting controls)。
原则上,可以尝试使用光标位置报告( CPR
控制序列)来查看使用 CPL
后光标的位置,但即使这对某些“xterm模拟器”来说也是不可靠的。
顺便说一句, CPL
控制序列接受一个repeat参数,因此可以重写print语句以使用它(而不是重复控制序列)。
如果您想要更轻松一点,使用 CUU
(向上光标)控件可以与VT100配合使用,并且(如 CPL
)可以使用重复计数进行参数化。那是"\033[A"
:
CSI Ps A Cursor Up Ps Times (default = 1) (CUU).
答案 1 :(得分:0)
为什么不使用curses?它在Linux,OSX中原生运行,现在还有一个Windows implementation(报告为here)。
以下示例在大多数平台上都是可靠的:
from curses import wrapper
import time
def print_over(scr, s):
scr.clear()
scr.addstr(5, 0, s)
scr.refresh()
def main(scr):
for i in range(10, 110, 10):
print_over(scr,'Progress: %d %%'%i)
time.sleep(1)
wrapper(main)
修改强>
这是另一个不清除整个屏幕的例子:
from curses import tparm, tigetstr, setupterm
import time
def tput(cmd, *args):
print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput
class window():
def __init__(s, x, y, w, h):
s.x, s.y, s.w, s.h = x, y, w, h # store window coordinates and size
def __enter__(s):
tput('sc') # saves current cursor position
s.clear() # clears the window
return s
def __exit__(s, exc_type, exc_val, exc_tb):
tput('rc') # restores cursor position
def clear(s, fill=' '):
for i in range(s.h):
tput('cup', s.y+i, s.x) # moves cursor to the leftmost column
print (fill*s.w, end='')
def print_over(s, msg, x, y):
tput('cup', s.y+y, s.x+x)
print (msg, end='')
setupterm()
with window(x=5, y=10, w=80, h=5) as w:
for i in range(10, 110, 10):
w.clear()
w.print_over('Progress: %d %%'%i, 5, 2)
time.sleep(1)
在这里另一个覆盖最后一行:
from curses import tparm, tigetstr, setupterm
import time
def tput(cmd, *args):
print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput
setupterm()
for i in range(10, 110, 10):
tput('el') # clear to end of line
print (' Progress: %d %%'%i, end='\r')
time.sleep(1)
基本上,原则是始终使用curses
和tput commands来避免任何显式转义字符。
请注意,您可能需要刷新标准输出或仅使用python -u
启动脚本。