更高效的基于文本的加载栏

时间:2014-05-04 21:27:55

标签: python

我正在制作一个带有#34;加载栏的程序"但我无法弄清楚如何缩短代码。对于我所知道的一切来说,这可能是一个简单的解决方案,但对于我的生活,我无法弄明白。以下是我到目前为止所做的尝试:

def ldbar():
    print "Load: 1%"
    time.sleep(0.5)
    os.system('clear')
    print "Load: 2%"
    time.sleep(0.5)
    os.system('clear')
    print "Load: 3%"
    time.sleep(0.5)
    os.system('clear')
    print "Load: 4%"
    time.sleep(0.5)
    os.system('clear')
    print "Load: 5%"
    #So on and so forth up to 100%

ldbar()

所以,就像我说的那样,无论如何我可以缩短它吗?

3 个答案:

答案 0 :(得分:2)

这应该有效:

def ldbar():
    for i in range(1, 100):
        print "Load: {}%\r".format(i),
        sys.stdout.flush()
        time.sleep(0.5)

ldbar()

它使用for循环来避免一遍又一遍地使用相同的代码。在print语句中,我使用\r将光标移动到行的前面,允许它被覆盖,这就是使用sys.stdout.flush来确保输出没有换行的原因(注意print语句末尾的逗号表示不应打印​​换行符。

对于Python 3,你会使用它(但我认为你使用的是python 2):

def ldbar():
    for i in range(1, 100):
        print("Load: {}%\r".format(i), end="")
        sys.stdout.flush()
        time.sleep(0.5)

ldbar()

答案 1 :(得分:2)

这是一个使用context manager的好版本:

from contextlib import contextmanager
import sys

@contextmanager
def scoped_progress_bar(num_steps, message):
    class Stepper(object):
        '''
        Helper class that does the work of actually advancing the progress bar message
        '''
        def __init__(self, num_steps, message):
            self.current_step = 0.0
            self.num_steps    = num_steps
            self.message      = message

        def step(self, steps = 1.0):
            self.current_step += steps
            sys.stdout.write('\r{}:{}%'.format(message, (self.current_step/self.num_steps)*100))
            sys.stdout.flush()


    stepper = Stepper(num_steps, message) # This is where we actually create the progress bar
    yield stepper.step                    # This is where we do the yield secret sauce to let the user step the bar.
    # Finally when the context block exits we wind up back here, and advance the bar to 100% if we need to
    if stepper.current_step < stepper.num_steps:
        stepper.step(stepper.num_steps - stepper.current_step)

这种方法的优点是

  1. 您可以指定任意数量的步骤
  2. 您可以执行任意数量的步骤
  3. 即使您没有达到步数的末尾,上下文管理器也会始终打印100%
  4. 您可以指定任意消息
  5. 用法:

    with scoped_progress_bar(10, 'loading') as step:
        for i in xrange(7):
            step()
            time.sleep(0.5)
    

    打印哪些:

    loading: 10%
    loading: 20%
    ...
    loading: 70%
    loading: 100%
    

    你的情况可能有点矫枉过正,但我​​认为我会提供以防万一。

    所有这些答案都需要注意的一点是,他们假设您在推进进度条的过程中不会打印出来。这样做仍然会很好,它可能看起来不像你期望的那样。

答案 2 :(得分:1)

首先,使用进度条模块(https://pypi.python.org/pypi/progressbar),它已经完成了您从文本模式进度条中获得的所有内容,然后是一些。

现在为了修复你的具体实现,你要做的是写一个没有行返回的stdout(或stderr)条,然后删除它,然后再画一次。你是这样做的:

import sys
import time

sys.stdout.write("0%")
# stdout is line-buffered and you didn't print a newline,
# so nothing will show up unless you explicitly call flush.
sys.stdout.flush()

time.sleep(2)

# Move the cursor back to the beginning of the line
# and overwrite the characters.
sys.stdout.write("\r1%")
sys.stdout.flush()

time.sleep(2)
sys.stdout.write("\r2%")
sys.stdout.flush()

# etc.

但实际上,请使用进度条。