如何在python中覆盖以前的打印到stdout?

如果我有以下代码:

for x in range(10):
     print x

我会得到的输出

1
2
etc..

我想要做的是不是打印换行符,而是要替换之前的值并用同一行上的新值覆盖它。

ccwhite1 asked 2019-08-13T11:08:15Z
15个解决方案
99 votes

一种方法是使用回车符('\r')字符返回到行的开头而不前进到下一行:

for x in range(10):
    print '{0}\r'.format(x),
print

print语句末尾的逗号告诉它不要转到下一行。 最后一个打印语句前进到下一行,因此您的提示不会覆盖您的最终输出。

Mike DeSimone answered 2019-08-13T11:08:36Z
79 votes

由于我最终通过谷歌来到这里,但我使用的是Python 3,以下是如何在Python 3中使用它:

for x in range(10):
    print("Progress {:2.1%}".format(x / 10), end="\r")

相关答案:如何在打印声明后抑制换行符?

Pascal answered 2019-08-13T11:09:08Z
23 votes

@Mike DeSimone的回答可能大部分时间都有效。 但...

for x in ['abc', 1]:
    print '{}\r'.format(x),

-> 1bc

这是因为'\r'只返回到行的开头但没有清除输出。

编辑:更好的解决方案(比我下面的旧提议)

如果POSIX支持对您来说足够了,以下将清除当前行并将光标留在其开头:

print '\x1b[2K\r',

它使用ANSI转义码来清除终端线。 更多信息可以在维基百科和这个精彩的演讲中找到。

老答案

我发现的(不那么好)解决方案看起来像这样:

last_x = ''
for x in ['abc', 1]:
    print ' ' * len(str(last_x)) + '\r',
    print '{}\r'.format(x),
    last_x = x

-> 1

一个优点是它也适用于Windows。

Nagasaki45 answered 2019-08-13T11:10:19Z
21 votes

在访问此主题之前我有同样的问题。 对我来说,sys.stdout.write只有在我正确刷新缓冲区时才有效,即

for x in range(10):
    sys.stdout.write('\r'+str(x))
    sys.stdout.flush()

如果没有刷新,结果只会在脚本末尾打印出来

user2793078 answered 2019-08-13T11:10:51Z
17 votes

取消换行并打印\r

print 1,
print '\r2'

或者写信给stdout:

sys.stdout.write('1')
sys.stdout.write('\r2')
Ignacio Vazquez-Abrams answered 2019-08-13T11:11:23Z
7 votes

我无法在此页面上获得任何解决方案来为IPython工作,但是@ Mike-Desimone的解决方案稍有不同就完成了这项工作:而不是使用回车符终止该行,启动该行 回车:

for x in range(10):
    print '\r{0}'.format(x),

另外,这种方法不需要第二个打印语句。

David Marx answered 2019-08-13T11:11:55Z
6 votes

试试这个:

import time
while True:
    print("Hi ", end="\r")
    time.sleep(1)
    print("Bob", end="\r")
    time.sleep(1)

它对我有用。 hi部分正在覆盖前一行。

警告!

如果您打印hi,然后使用\r打印hello,您将获得hillo,因为输出写入前两个字母。 如果您打印hi的空格(此处未显示),则会输出hi.要解决此问题,请使用\r打印空格。

Stiffy2000 answered 2019-08-13T11:12:35Z
4 votes
for x in range(10):
    time.sleep(0.5) # shows how its working
    print("\r {}".format(x), end="")

time.sleep(0.5)用于显示如何擦除先前的输出并打印新输出"\ R" 当它在打印消息开始时,它将在新输出之前擦除先前的输出。

Rubixred answered 2019-08-13T11:13:02Z
3 votes

接受的答案并不完美。 首先打印的行将保留在那里,如果您的第二个打印不覆盖整个新行,您将最终得到垃圾文本。

为了说明问题,将此代码保存为脚本并运行它(或者只是看看):

import time

n = 100
for i in range(100):
    for j in range(100):
        print("Progress {:2.1%}".format(j / 100), end="\r")
        time.sleep(0.01)
    print("Progress {:2.1%}".format(i / 100))

输出看起来像这样:

Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%

对我有用的是在离开永久印刷品之前清除线条。 随意调整您的具体问题:

import time

ERASE_LINE = '\x1b[2K' # erase line command
n = 100
for i in range(100):
    for j in range(100):
        print("Progress {:2.1%}".format(j / 100), end="\r")
        time.sleep(0.01)
    print(ERASE_LINE + "Progress {:2.1%}".format(i / 100)) # clear the line first

现在按预期打印:

Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
mimoralea answered 2019-08-13T11:13:52Z
3 votes

这适用于Windows和python 3.6

import time
for x in range(10):
    time.sleep(0.5)
    print(str(x)+'\r',end='')
Siddhant Sadangi answered 2019-08-13T11:14:18Z
2 votes

我使用以下方法创建了一个加载器:

for i in range(10):
    print(i*'.', end='\r')
Henrique Schumann answered 2019-08-13T11:14:45Z
1 votes

@ Nagasaki45的答案是更清洁,更具"即插即用的版本:

def print_statusline(msg: str):
    last_msg_length = len(print_statusline.last_msg) if hasattr(print_statusline, 'last_msg') else 0
    print(' ' * last_msg_length, end='\r')
    print(msg, end='\r')
    sys.stdout.flush()  # Some say they needed this, I didn't.
    print_statusline.last_msg = msg

# Then simply use like this:
for msg in ["Initializing...", "Initialization successful!"]:
    print_statusline(msg)
    time.sleep(1)

# If you want to check that the line gets cleared properly:
for i in range(9, 0, -1):
    print_statusline("{}".format(i) * i)
    time.sleep(0.5)

与其他许多答案不同,它可以使用不同长度的字符串正常工作,因为它会清空带有空格的行。 也适用于Windows。

erb answered 2019-08-13T11:15:19Z
1 votes

我有点惊讶没有人使用退格字符。 这是使用它的人。

import sys
import time

secs = 1000

while True:
    time.sleep(1)  #wait for a full second to pass before assigning a second
    secs += 1  #acknowledge a second has passed

    sys.stdout.write(str(secs))

    for i in range(len(str(secs))):
        sys.stdout.write('\b')
David Philipe Gil answered 2019-08-13T11:15:45Z
0 votes

这是我的解决方案! Windows 10,Python 3.7.1

我不确定为什么这段代码有效,但它完全删除了原始行。 我从以前的答案中编译了它。 其他答案只会将线条返回到开头,但如果你之后有一条较短的线条,它看起来就像hello变成了byelo

import sys
#include ctypes if you're on Windows
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
#end ctypes

def clearline(msg):
    CURSOR_UP_ONE = '\033[K'
    ERASE_LINE = '\x1b[2K'
    sys.stdout.write(CURSOR_UP_ONE)
    sys.stdout.write(ERASE_LINE+'\r')
    print(msg, end='\r')

#example
ig_usernames = ['beyonce','selenagomez']
for name in ig_usernames:
    clearline("SCRAPING COMPLETE: "+ name)

输出 - 每行都将被重写,而不显示任何旧文本:

SCRAPING COMPLETE: selenagomez

下一行(完全在同一行重写):

SCRAPING COMPLETE: beyonce
kpossibles answered 2019-08-13T11:16:34Z
-2 votes

这里有一个简单的代码,对您有用!

import sys
import time

for i in range(10):
    sys.stdout.write("\r" + i)
    sys.stdout.flush()
    time.sleep(1)
Malek B. answered 2019-08-13T11:17:01Z
translate from https://stackoverflow.com:/questions/5419389/how-to-overwrite-the-previous-print-to-stdout-in-python