我正在尝试为一个长时间运行的函数在进度条下面实现一个简单的微调工具(使用改编自this answer的代码)。
[######## ] x%
/ Compressing filename
我让压缩和进度条在我的脚本的主线程中运行,而微调在另一个线程中运行,所以它实际上可以在压缩发生时旋转。但是,我在进度条和微调器中都使用了curses
,而且两者都使用curses.refresh()
有时终端会随机输出胡言乱语,我不确定为什么。我认为这是由于微调器的多线程特性,因为当我禁用微调器时,问题就消失了。
以下是微调器的伪代码:
def start(self):
self.busy = True
global stdscr
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
threading.Thread(target=self.spinner_task).start()
def spinner_task(self):
while self.busy:
stdscr.addstr(1, 0, next(self.spinner_generator))
time.sleep(self.delay)
stdscr.refresh()
下面是进度条的伪代码:
progress_bar = "\r[{}] {:.0f}%".format("#" * block + " " * (bar_length - block), round(progress * 100, 0))
progress_file = " {} {}".format(s, filename)
stdscr.clrtoeol()
stdscr.addstr(1, 1, " ")
stdscr.clrtoeol()
stdscr.addstr(0, 0, progress_bar)
stdscr.addstr(1, 1, progress_file)
stdscr.refresh()
从main()
调用,如下所示:
spinner.start()
for each file:
update_progress_bar
compress(file)
spinner.stop()
为什么输出有时会损坏?是不是因为有单独的线程?如果是这样的话,有什么更好的设计方法的建议吗?
发布于 2018-07-13 10:02:14
如果这是您唯一使用curses
模块的地方,最好的解决方案就是停止使用它。
您在这里真正使用的curses
的唯一功能是它清除屏幕和移动光标的能力。这可以很容易地通过直接输出适当的控制序列来复制,例如:
sys.stdout.write("\x1b[f\x1b[J" + progress_bar + "\n" + progress_file)
\x1b[f
序列将光标移动到1,1,\x1b[J
清除从光标位置到屏幕末尾的所有内容。
不需要额外的调用来刷新屏幕,或者在完成后重新设置它。如果需要,您可以再次输出"\x1b[f\x1b[J"
以清除屏幕。
诚然,这种方法确实假设用户正在使用VT100兼容的终端。但是,没有实现此标准的终端实际上已经绝迹,因此这可能是一个安全的假设。
https://stackoverflow.com/questions/51315269
复制相似问题