异步进度旋转器

3
这是进度旋转器的代码:
import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()
for _ in range(50):
    sys.stdout.write(spinner.next())
    sys.stdout.flush()
    time.sleep(10)
    sys.stdout.write('\b')

输出

python2.7 test.py
|

由于循环休眠了10秒钟,所以它正在缓慢旋转...

在进程休眠的同时如何保持旋转状态?


你的问题不够清楚。你是希望每次运行 cmd 时光标稍微转动一下(这是你的代码所做的),还是希望在 cmd 运行期间光标快速旋转? - Rory Daulton
@ 它转得非常慢,命令执行没有完成 - meteor23
如果 cmd 无法完成,那是与旋转光标无关的另一个问题。那么你到底在问什么呢? - Rory Daulton
@Rory Daulton,问题已经编辑过了。 - meteor23
3个回答

7

你需要创建一个单独的线程。下面的示例大致展示了如何实现,但这只是一个简单的示例。

import sys
import time

import threading


class SpinnerThread(threading.Thread):

    def __init__(self):
        super().__init__(target=self._spin)
        self._stopevent = threading.Event()

    def stop(self):
        self._stopevent.set()

    def _spin(self):

        while not self._stopevent.isSet():
            for t in '|/-\\':
                sys.stdout.write(t)
                sys.stdout.flush()
                time.sleep(0.1)
                sys.stdout.write('\b')


def long_task():
    for i in range(10):
        time.sleep(1)
        print('Tick {:d}'.format(i))


def main():

    task = threading.Thread(target=long_task)
    task.start()

    spinner_thread = SpinnerThread()
    spinner_thread.start()

    task.join()
    spinner_thread.stop()


if __name__ == '__main__':
    main()

有没有一种方法可以使用asyncio.to_thread函数而不是继承自Thread来实现? - Snap

4
你可以将睡眠分为小的时间段,直到达到10秒钟:
import sys, time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()
end_time = time.time() + 10
while time.time() < end_time:
    sys.stdout.write(spinner.next())
    sys.stdout.flush()
    time.sleep(0.2) # adjust this to change the speed
    sys.stdout.write('\b')

但是这会阻塞你的主线程,因此只有在你想要等待10秒而不在Python程序中执行其他操作(例如等待某个外部进程完成)时才有用。

如果您希望在旋转器旋转时运行其他Python代码,则需要两个线程--一个用于旋转器,另一个用于主要工作。您可以像这样设置:

import sys, time, threading

def spin_cursor():
    while True:
        for cursor in '|/-\\':
            sys.stdout.write(cursor)
            sys.stdout.flush()
            time.sleep(0.1) # adjust this to change the speed
            sys.stdout.write('\b')
            if done:
                return

# start the spinner in a separate thread
done = False
spin_thread = threading.Thread(target=spin_cursor)
spin_thread.start()

# do some more work in the main thread, or just sleep:
time.sleep(10)

# tell the spinner to stop, and wait for it to do so;
# this will clear the last cursor before the program moves on
done = True
spin_thread.join()

# continue with other tasks
sys.stdout.write("all done\n")

0
生成两个线程,AB。线程A运行cmd直到完成。线程B显示旋转光标并等待线程A退出,这将在cmd完成时发生。此时,线程B清除旋转光标然后退出。
或者使用现有的库而不是重复造轮子。考虑使用progressbar库。你会想要使用RotatingMarker进度指示器。

我正在使用Python2.7,但是没有安装progressbar模块。最终用户无法安装模块。所以如果我能得到一个定制脚本就太好了。 - meteor23
1
我不会为你编写代码。我指导你朝正确的方向前进,现在轮到你尝试更新你的代码了。有一个与progressbar类似的姊妹库支持Python 3。简单的搜索就可以告诉你这一点。Stack Overflow并不是一个代码编写服务。 - ndmeiri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接