我希望使用\r
在Python中执行控制台进度条来清除显示。为了支持多行进度条(对于几个并行任务),我想知道是否可以为当前进程设置终端宽度,以便长行包裹?
例如,如果我将终端宽度设置为20
,我可以这样做我的进度条:
print '\r%-20s%-20s' % ('Task 1: 30%', 'Task 2: 60%'),
time.sleep(1)
print '\r%-20s%-20s' % ('Task 1: 35%', 'Task 2: 65%'),
我知道可以使用ncurses
(或使用ncurses
的进度条包),我只是想知道是否有一个解决方案没有使用{ {1}}。
我在https://stackoverflow.com/a/6420070/445810尝试了ncurses
,但它没有用,而且行仍然没有包裹。
谢谢!
答案 0 :(得分:0)
根据您使用的实际终端,使用指示的方法更改终端宽度(rxvt从xterm获得的功能,而该功能又是based on a feature from dtterm)可能/可能不起作用。但还有更直接的方式。
而不是写一个长行和希望终端将它包装起来,你可以
以下是一个例子:
import curses, time, sys
def go_to_top_left():
curses.putp(curses.tparm(curses.tigetstr("cup"),0,0))
def show_bar(n):
curses.putp(curses.tigetstr("rev"))
sys.stdout.write('.' * n)
sys.stdout.write('*')
curses.putp(curses.tigetstr("sgr0"))
curses.putp(curses.tigetstr("el"))
sys.stdout.write('\n')
sys.stdout.flush()
def clear_to_bottom():
curses.putp(curses.tigetstr("ed"))
def progress_bars():
curses.setupterm()
foo = 1
bar = 0
while foo < 50:
go_to_top_left()
show_bar(foo)
show_bar(bar)
bar = foo
foo = foo + 1
clear_to_bottom()
time.sleep(1)
progress_bars()
该示例使用curses包中的 terminfo 调用。与 termcap 一样,这些调用不会优化光标的移动,并且您可以控制实际清除屏幕的时间。如果你想完全免除清算,你必须做出几个关于
的假设(有人可能愿意提供一个硬编码等效于此示例作为&#34;改进&#34;)。
进一步阅读:
答案 1 :(得分:0)
您应该更好地适应终端大小的变化,而不是尝试设置终端宽度。
这个小程序就是这样做的。 运行它并调整终端的大小;观察输出调整大小。
我从this elaborate example获取了IOCTL代码。
import fcntl
import signal
import struct
import sys
import termios
import time
def ioctl_GWINSZ(fd): #### TABULATION FUNCTIONS
return struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
def draw_line(width, left_cap, body, right_cap):
w = sys.stdout.write
w(left_cap)
w(body * (width - 2))
w(right_cap)
def draw_rect(width, height):
draw_line(width, '/', '-', '\\')
for n in xrange(height - 3):
draw_line(width, '|', ' ', '|')
draw_line(width, '\\', '-', '/')
def draw_screen():
h, w = ioctl_GWINSZ(1) # of stdout.
draw_rect(w, h)
sys.stdout.write('Rows: %3d, Cols: %3d' % (h, w))
sys.stdout.flush()
def on_winch(*ignored):
sys.stdout.write('\n')
draw_screen()
if __name__ == '__main__':
draw_screen()
signal.signal(signal.SIGWINCH, on_winch)
while True:
time.sleep(0.1)