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

ccw*_*te1 97 python

如果我有以下代码:

for x in range(10):
     print x
Run Code Online (Sandbox Code Playgroud)

我会得到的输出

1
2
etc..
Run Code Online (Sandbox Code Playgroud)

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

Mik*_*one 100

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

for x in range(10):
    print '{0}\r'.format(x),
print
Run Code Online (Sandbox Code Playgroud)

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

  • 这是在Python 2.6中引入的(我被告知)是在Python 3中格式化字符串的标准方法; '%`运算符已弃用.基本上,所有字符串现在都有[格式](http://docs.python.org/library/stdtypes.html#str.format)方法.在这种情况下,`{0}`表示"format()`"的第一个参数(计数从0开始). (7认同)
  • 如果你想跨终端,`re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or '')` 会给你用户拥有的任何终端的正确擦除到行尾字符串。记得用类似 `curses.setupterm(fd=sys.stdout.fileno())` 初始化 `curses`,并使用 `sys.stdout.isatty()` 来确保你的输出没有被重定向到一个文件. 有关具有光标控制和颜色支持的完整 Python 模块,请参阅 http://code.activestate.com/recipes/475116/。 (3认同)

Pas*_*cal 94

由于我最终通过Google访问,但我使用的是Python 3,以下是Python 3的工作原理:

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

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

  • 在ipython笔记本中,我必须这样做:`print("\n",message,end ="")` (12认同)
  • 我试过这个,它大多工作正常。唯一的问题是它没有删除该行上的先前输出,例如:如果您的第一个循环打印 `testing` 并且第二个循环打印 `test`,则第二遍后的输出仍然是 `testing` - 现在我看到 @ Nagasaki45 指出了这一点 (3认同)
  • 这非常有效,它不会删除该行,但在接下来的打印中使用足够的空白就可以完成这项工作(尽管它并不优雅)。我可能要补充的一点是,这在 VS Code 的调试控制台中不起作用,但在终端中起作用。 (2认同)

Nag*_*i45 26

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

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

-> 1bc
Run Code Online (Sandbox Code Playgroud)

这是因为'\r'它只返回到行的开头但不清除输出.

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

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

print '\x1b[2K\r',
Run Code Online (Sandbox Code Playgroud)

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

老答案

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

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

-> 1
Run Code Online (Sandbox Code Playgroud)

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


use*_*078 24

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

for x in range(10):
    sys.stdout.write('\r'+str(x))
    sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

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


Ign*_*ams 17

取消换行并打印\r.

print 1,
print '\r2'
Run Code Online (Sandbox Code Playgroud)

或者写信给stdout:

sys.stdout.write('1')
sys.stdout.write('\r2')
Run Code Online (Sandbox Code Playgroud)

  • 这也适用于Jupyter/IPython. (2认同)

Dav*_*arx 7

我无法让这个页面上的任何解决方案适用于IPython,但是@ Mike-Desimone的解决方案稍有不同就完成了这项工作:不是使用回车符终止该行,而是使用回车符开始行:

for x in range(10):
    print '\r{0}'.format(x),
Run Code Online (Sandbox Code Playgroud)

此外,此方法不需要第二个打印语句.

  • @Alexandre它在IPython或其后继者Jupyter中运行良好.您需要刷新缓冲区.http://stackoverflow.com/questions/17343688/how-to-flush-the-printed-statements-in-ipython (2认同)

Sti*_*000 7

试试这个:

import time
while True:
    print("Hi ", end="\r")
    time.sleep(1)
    print("Bob", end="\r")
    time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

它对我有用.该 end="\r"部分正在覆盖前一行.

警告!

如果你打印出来hi,然后hello使用打印输出\r,你会得到hillo因为输出写了前两个字母.如果您打印出hi空格(这里没有显示),那么它将输出hi.要解决此问题,请使用打印空格\r.


erb*_*erb 7

这是@Nagasaki45 答案的更清洁、更“即插即用”的版本。与此处的许多其他答案不同,它适用于不同长度的字符串。它通过清除与打印的最后一行长度一样多的空格来实现这一点。也适用于 Windows。

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
Run Code Online (Sandbox Code Playgroud)

用法

只需像这样使用它:

for msg in ["Initializing...", "Initialization successful!"]:
    print_statusline(msg)
    time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

这个小测试表明,即使长度不同,线条也能正确清除:

for i in range(9, 0, -1):
    print_statusline("{}".format(i) * i)
    time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解决方案,因为它优雅地将先前的输出清理到其全长,而不仅仅是打印任意数量的空格(这是我以前使用的!)谢谢 (5认同)

小智 7

这适用于 Windows 和 python 3.6

import time
for x in range(10):
    time.sleep(0.5)
    print(str(x)+'\r',end='')
Run Code Online (Sandbox Code Playgroud)


小智 5

for x in range(10):
    time.sleep(0.5) # shows how its working
    print("\r {}".format(x), end="")
Run Code Online (Sandbox Code Playgroud)

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


mim*_*lea 5

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

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

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))
Run Code Online (Sandbox Code Playgroud)

输出将如下所示:

Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
Run Code Online (Sandbox Code Playgroud)

对我有用的是在留下永久印刷品之前清除线条。随时根据您的具体问题进行调整:

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
Run Code Online (Sandbox Code Playgroud)

现在它按预期打印:

Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
Run Code Online (Sandbox Code Playgroud)