打印到同一行而不是python中的新行


85

基本上,我想做的和这个家伙相反。

Python脚本:每次将新行打印到外壳程序,而不是更新现有行

我有一个程序,告诉我它有多远。

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete"

因此,如果len(some_list)为50,我将最后一行打印50遍。我想打印一行并继续更新该行。我知道我知道这可能是您整天都会阅读的最棘手的问题。我只是想不通我需要输入到Google以获得答案的四个词。

更新!我尝试了mvds的建议,认为正确。新密码

print percent_complete,"           \r",

完成百分比只是一个字符串(我是第一次尝试抽象,现在是抽象的)。现在的结果是它运行该程序,直到程序结束后才打印任何内容,然后仅在一行上打印“ 100%完成”。

没有回车符(但逗号,是mvds建议的一半),直到最后都不会打印。然后打印:

0 percent complete     2 percent complete     3 percent complete     4 percent complete    

等等。因此,现在的新问题是,直到程序完成,逗号才会打印出来。

使用回车符且没有逗号时,其行为与未使用逗号完全相同。


您可能还需要检查一下,sys.stdout.isatty()以免在终端机上不运行时不吐这些东西。
mvds 2010年

我是从终端运行的……虽然好想。我确定我会在某个时候需要它。
chriscauley,2010年

1
顺便说一句,背景是,在几种语言中,\ n(我们现在省略了)充当隐式信号刷新到stdout。否则,很多人会感到困惑。
mvds

Answers:


85

这叫做回车,或者 \r

使用

print i/len(some_list)*100," percent complete         \r",

逗号防止打印添加换行符。(空格将使行与先前的输出保持清晰)

另外,不要忘了以终止,print ""以获得至少一个最终的换行符!


12
只要确保您始终在该行上打印相同数量的数据(或比以前任何打印都多),否则最终将导致混乱。
尼古拉斯·奈特

如此接近...我将用这个结果来更新问题。
chriscauley,2010年

2
@dustynachos:呵呵,忘了那皱纹。请参阅Python输出缓冲问题:stackoverflow.com/questions/107705/python-output-buffering
Nicholas Knight,2010年

1
@dustynachos :(或仅在每次打印调用后使用sys.stdout.flush(),如果您不关心其余程序的输出缓冲,则可能会更好)
Nicholas Knight

2
这对我不起作用。实际上,我已经尝试了无数次,但对我没有用。我在Mac上使用iterm2,但大多数时候我都被ssh进入linux服务器。我从来没有找到一种可以实际起作用的方法。
bgenchel '18

35

对我而言,有效的方法是Remi和siriusd的答案​​的组合:

from __future__ import print_function
import sys

print(str, end='\r')
sys.stdout.flush()

33

在python 3.x中,您可以执行以下操作:

print('bla bla', end='')

(也可以在Python 2.6或2.7中使用,方法是放在from __future__ import print_function脚本/模块的顶部)

Python控制台进度栏示例:

import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    n=0
    while n<total:
        done = '#'*(n+1)
        todo = '-'*(total-n-1)
        s = '<{0}>'.format(done+todo)
        if not todo:
            s+='\n'        
        if n>0:
            s = '\r'+s
        print(s, end='')
        yield n
        n+=1

# example for use of status generator
for i in range_with_status(10):
    time.sleep(0.1)

\ r似乎也添加了新行
fccoelho 2013年

2
这摆脱了换行符,但不允许覆盖,我认为这是作者想要的。
bgenchel '18

1
@bgenchel与'\ r'一起使用(如代码示例中所示),它完全满足OP的要求
Milo Wielondek

19

在Python 3.3+中,您不需要sys.stdout.flush()print(string, end='', flush=True)作品。

所以

print('foo', end='')
print('\rbar', end='', flush=True)

将用“ bar”覆盖“ foo”。


2
只要打印的文本以"\r"。结尾,它就可以工作。
bli

13

对于控制台,您可能需要

sys.stdout.flush()

强制更新。我认为,在打印中使用将阻止stdout刷新,并且以某种方式不会更新


除非我在print语句后立即运行此命令,否则终结者在使用print(“ ...”,end ='\ r')时仅每30秒刷新一行。感谢
Bryce Guinta '16

4

游戏晚了-但由于没有一个答案对我有用(我没有全部尝试),而且我在搜索中多次遇到了这个答案……在python 3中,这种解决方案非常优雅而且我相信它确实符合作者的要求,并且在同一行上更新了一条声明。请注意,如果行缩小而不是增长,则可能必须执行一些特殊的操作(例如,使字符串固定长度,并在末尾添加空格)

if __name__ == '__main__':
    for i in range(100):
        print("", end=f"\rPercentComplete: {i} %")
        time.sleep(0.2)

python最简单,最干净的选项=> 3.6
DaveR

3

这对我有用,对它进行一次破解以查看是否可能,但从未在我的程序中实际使用过(GUI更好):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
    print clear+f % (i*100//123),
    time.sleep(0.4)
raw_input('\nDone')

2
import time
import sys


def update_pct(w_str):
    w_str = str(w_str)
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(" " * len(w_str))
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(w_str)
    sys.stdout.flush()

for pct in range(0, 101):
    update_pct("{n}%".format(n=str(pct)))
    time.sleep(0.1)

\b将光标移回一个空的位置
所以我们将它回来的路上所有的行的开头
然后我们写空间清除当前行-为我们写空间光标向前移动/右一个
那么接下来,我们有在我们写入新数据之前将光标移至行首

使用Python 2.7在Windows cmd上测试


1

像这样尝试:

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete",

(以逗号结尾。)


这只是将新文本附加到旧文本(功能相似但难看)。
chriscauley,2010年

1

如果您使用的是Spyder,则这些行将与所有先前的解决方案一起连续打印。一种避免这种情况的方法是使用:

for i in range(1000):
    print('\r' + str(round(i/len(df)*100,1)) + '% complete', end='')
    sys.stdout.flush()

这对我来说是唯一可行的解​​决方案(Python 3.8,Windows,PyCharm)。
z33k

0

基于雷米的回答Python 2.7+使用这样的:

from __future__ import print_function
import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    import sys
    n = 0
    while n < total:
        done = '#' * (n + 1)
        todo = '-' * (total - n - 1)
        s = '<{0}>'.format(done + todo)
        if not todo:
            s += '\n'
        if n > 0:
            s = '\r' + s
        print(s, end='\r')
        sys.stdout.flush()
        yield n
        n += 1


# example for use of status generator
for i in range_with_status(50):
    time.sleep(0.2)

0

对于Python 3.6+因任何list而不仅仅是intS,以及使用控制台窗口的整个宽度,而不是跨越到一个新行,你可以使用以下命令:

注意:请注意,该功能get_console_with()仅在基于Linux的系统上可用,因此您必须重写该功能才能在Windows上使用。

import os
import time

def get_console_width():
    """Returns the width of console.

    NOTE: The below implementation works only on Linux-based operating systems.
    If you wish to use it on another OS, please make sure to modify it appropriately.
    """
    return int(os.popen('stty size', 'r').read().split()[1])


def range_with_progress(list_of_elements):
    """Iterate through list with a progress bar shown in console."""

    # Get the total number of elements of the given list.
    total = len(list_of_elements)
    # Get the width of currently used console. Subtract 2 from the value for the
    # edge characters "[" and "]"
    max_width = get_console_width() - 2
    # Start iterating over the list.
    for index, element in enumerate(list_of_elements):
        # Compute how many characters should be printed as "done". It is simply
        # a percentage of work done multiplied by the width of the console. That
        # is: if we're on element 50 out of 100, that means we're 50% done, or
        # 0.5, and we should mark half of the entire console as "done".
        done = int(index / total * max_width)
        # Whatever is left, should be printed as "unfinished"
        remaining = max_width - done
        # Print to the console.
        print(f'[{done * "#"}{remaining * "."}]', end='\r')
        # yield the element to work with it
        yield element
    # Finally, print the full line. If you wish, you can also print whitespace
    # so that the progress bar disappears once you are done. In that case do not
    # forget to add the "end" parameter to print function.
    print(f'[{max_width * "#"}]')


if __name__ == '__main__':
    list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    for e in range_with_progress(list_of_elements):
        time.sleep(0.2)


0

如果您使用的是Python 3,则此功能非常适合您。

print(value , sep='',end ='', file = sys.stdout , flush = False)

0

对于Python 3+

for i in range(5):
    print(str(i) + '\r', sep='', end ='', file = sys.stdout , flush = False)

0

只是我自己想出了显示倒计时的功能,但它也可以发挥一定的作用。

import time
#Number of seconds to wait
i=15
#Until seconds has reached zero
while i > -1:
    #Ensure string overwrites the previous line by adding spaces at end
    print("\r{} seconds left.   ".format(i),end='')
        time.sleep(1)
        i-=1
    print("") #Adds newline after it's done

只要'/ r'之后的内容与前一个字符串相同或更长(包括空格),它将在同一行覆盖它。只要确保您包含end ='',否则它将打印到换行符。希望有帮助!


0

对于对象“ pega”,它提供StartRunning(),StopRunning(),boolean getIsRunning()和整数getProgress100()返回值(范围为0到100),这在运行时提供了文本进度栏。

now = time.time()
timeout = now + 30.0
last_progress = -1

pega.StartRunning()

while now < timeout and pega.getIsRunning():
    time.sleep(0.5)
    now = time.time()

    progress = pega.getTubProgress100()
    if progress != last_progress:
        print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", end='', flush=True)
        last_progress = progress

pega.StopRunning()

progress = pega.getTubProgress100()
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", flush=True)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.