【问题标题】:asynchronous progress spinner异步进度微调器
【发布时间】:2018-02-18 17:29:59
【问题描述】:

这是进度微调器的代码:

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 运行时快速转动?
  • @它转得很慢,cmd 执行没有完成
  • 如果cmd 未完成,这是与旋转光标不同的问题。那么究竟你在问什么?
  • @Rory Daulton,现在编辑问题。

标签: python progress


【解决方案1】:

您必须创建一个单独的线程。下面的示例大致显示了如何做到这一点。然而,这只是一个简单的例子。

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()

【讨论】:

    【解决方案2】:

    你可以小步睡到 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")
    

    【讨论】:

      【解决方案3】:

      产生两个线程,AB。线程 A 运行 cmd 完成。线程B 显示旋转光标并等待线程A 退出,这将在cmd 完成时发生。此时,线程B 清除旋转光标然后退出。

      或者使用现有的库而不是重新发明轮子。考虑progressbar 库。您将需要RotatingMarker 进度指示器。

      【讨论】:

      • 我用的是python2.7,进度条不可用。最终用户无法安装模块。所以如果我得到自定义脚本会很棒
      • 我不会为你写代码。我为您指明了正确的方向,现在轮到您尝试更新代码了。有一个支持 Python 3 的进度条的姊妹库。一个简单的搜索就会告诉你。 Stack Overflow 不是代码编写服务。
      猜你喜欢
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 2018-02-15
      • 2014-05-02
      • 1970-01-01
      相关资源
      最近更新 更多