Python CLI 进度 bar/spinner 没有迭代
Python CLI Progress bar/spinner WITHOUT iteration
在执行 Python 脚本时,关于终端中进度条显示的问题很多,但每一个问题都基于一个循环,您可以在循环中执行操作,然后更新进度图形.
不幸的是,我想显示其进度的函数——或者至少是一个微调器对象来显示它正在工作——是一个我不能(至少真的,真的不应该)的黑盒子改变。本质上,我想做的是:
#pseudocode input
print('Loading')
spinner.begin()
blackbox() #a few thousand operations happen in here
spinner.end()
print('Finished')
#pseudocode output
Loading.
Loading..
Loading...
Loading.
Loading..
Loading...
Finished
尽管理想情况下这将是省略号的动画而不是打印多行。在我什至可以开始构建愚蠢的 ascii 动画之前,有一个主要障碍:
有没有办法同时运行spinner
和blackbox()
?或者,是否有黑客可以暂停 blackbox()
,无论其内容如何,每隔几百毫秒,更新微调器图形,然后从中断处恢复?
我已经用 progress 模块试过了,但没有成功...我什至无法让示例代码运行,它在我开始迭代后就挂了,直到我按 Ctrl+C出来了。
您可能想要使用线程 (import threading
)。让 spinner.begin()
启动一个线程来打印您的消息,然后让您的黑盒 运行,然后让 spinner.end()
使用队列 (from Queue import Queue
) 向线程发送完成消息或某事,join()
线程并继续做你正在做的事。
作为一种设计选择,将指纹隐藏在更深的地方,而不是与开始和结束调用位于同一代码块中。
Threads 可能是完成这项工作的最简单方法。这是一个大大简化的版本,应该可以理解这一点。我不确定你是否真的有 spinner
功能,所以我自己做了。
import threading
import time
def blackbox():
time.sleep(10)
thread = threading.Thread(target=blackbox)
thread.start()
eli_count = 0
while thread.is_alive():
print('Loading', '.'*(eli_count+1), ' '*(2-eli_count), end='\r')
eli_count = (eli_count + 1) % 3
time.sleep(0.1)
thread.join()
print('Done ')
因此,在 blackbox
运行时,加载消息会定期更新。完成后,将加入线程并将加载消息替换为已完成的消息。
我喜欢为此使用 alive_progress
。
from typing import ContextManager, Optional
from alive_progress import alive_bar
def spinner(title: Optional[str] = None) -> ContextManager:
"""
Context manager to display a spinner while a long-running process is running.
Usage:
with spinner("Fetching data..."):
fetch_data()
Args:
title: The title of the spinner. If None, no title will be displayed.
"""
return alive_bar(monitor=None, stats=None, title=title)
安装:pip install alive-progress
在执行 Python 脚本时,关于终端中进度条显示的问题很多,但每一个问题都基于一个循环,您可以在循环中执行操作,然后更新进度图形.
不幸的是,我想显示其进度的函数——或者至少是一个微调器对象来显示它正在工作——是一个我不能(至少真的,真的不应该)的黑盒子改变。本质上,我想做的是:
#pseudocode input
print('Loading')
spinner.begin()
blackbox() #a few thousand operations happen in here
spinner.end()
print('Finished')
#pseudocode output
Loading.
Loading..
Loading...
Loading.
Loading..
Loading...
Finished
尽管理想情况下这将是省略号的动画而不是打印多行。在我什至可以开始构建愚蠢的 ascii 动画之前,有一个主要障碍:
有没有办法同时运行spinner
和blackbox()
?或者,是否有黑客可以暂停 blackbox()
,无论其内容如何,每隔几百毫秒,更新微调器图形,然后从中断处恢复?
我已经用 progress 模块试过了,但没有成功...我什至无法让示例代码运行,它在我开始迭代后就挂了,直到我按 Ctrl+C出来了。
您可能想要使用线程 (import threading
)。让 spinner.begin()
启动一个线程来打印您的消息,然后让您的黑盒 运行,然后让 spinner.end()
使用队列 (from Queue import Queue
) 向线程发送完成消息或某事,join()
线程并继续做你正在做的事。
作为一种设计选择,将指纹隐藏在更深的地方,而不是与开始和结束调用位于同一代码块中。
Threads 可能是完成这项工作的最简单方法。这是一个大大简化的版本,应该可以理解这一点。我不确定你是否真的有 spinner
功能,所以我自己做了。
import threading
import time
def blackbox():
time.sleep(10)
thread = threading.Thread(target=blackbox)
thread.start()
eli_count = 0
while thread.is_alive():
print('Loading', '.'*(eli_count+1), ' '*(2-eli_count), end='\r')
eli_count = (eli_count + 1) % 3
time.sleep(0.1)
thread.join()
print('Done ')
因此,在 blackbox
运行时,加载消息会定期更新。完成后,将加入线程并将加载消息替换为已完成的消息。
我喜欢为此使用 alive_progress
。
from typing import ContextManager, Optional
from alive_progress import alive_bar
def spinner(title: Optional[str] = None) -> ContextManager:
"""
Context manager to display a spinner while a long-running process is running.
Usage:
with spinner("Fetching data..."):
fetch_data()
Args:
title: The title of the spinner. If None, no title will be displayed.
"""
return alive_bar(monitor=None, stats=None, title=title)
安装:pip install alive-progress