29

在 Unix 上,我可以使用\r(carriage return) 或\b(backspace) 来覆盖 shell 中的当前行(打印已经可见的文本)。

我可以通过 Python 脚本在 Windows 命令行中实现相同的效果吗?

我尝试了 curses 模块,但它似乎在 Windows 上不可用。

4

11 回答 11

34

是的:

import sys
import time

def restart_line():
    sys.stdout.write('\r')
    sys.stdout.flush()

sys.stdout.write('some data')
sys.stdout.flush()
time.sleep(2) # wait 2 seconds...
restart_line()
sys.stdout.write('other different data')
sys.stdout.flush()
于 2009-01-21T14:15:10.657 回答
20

我知道这很旧,但我想告诉我的版本(它可以在我的电脑上的 cmd 中工作,但不能在空闲时)覆盖 Python 3 中的一行:

>>> from time import sleep
>>> for i in range(400):
>>>     print("\r" + str(i), end="")
>>>     sleep(0.5)

编辑: 它适用于 Windows 和 Ubuntu

于 2014-11-15T23:42:30.760 回答
14
import sys 
import time

for i in range(10):
    print '\r',         # print is Ok, and comma is needed.
    time.sleep(0.3)
    print i,
    sys.stdout.flush()  # flush is needed.

如果在 IPython-notebook 上,就像这样:

import time
from IPython.display import clear_output

for i in range(10):
    time.sleep(0.25)
    print(i)
    clear_output(wait=True)

http://nbviewer.ipython.org/github/ipython/ipython/blob/master/examples/notebooks/Animations%20Using%20clear_output.ipynb

于 2014-02-10T08:28:27.797 回答
7

我刚遇到这个问题。即使在 Windows 命令提示符中,您仍然可以使用\r,但是,它只会带您回到上一个换行符 ( \n)。

如果你做这样的事情:

cnt = 0
print str(cnt)
while True:
    cnt += 1
    print "\r" + str(cnt)

你会得到:

0
1
2
3
4
5
...

那是因为\r只回到最后一行。由于您已经使用最后一个打印语句编写了换行符,因此您的光标将从新空行的开头移动到同一新空行的开头。

为了说明,在您打印第一个 0 后,您的光标将位于此处:

0
| # <-- Cursor

当 you 时\r,您会转到行首。但你已经在这条线的开始了。

解决方法是避免打印\n字符,因此您的光标位于同一行并\r正确覆盖文本。你可以用print 'text',. 逗号可防止打印换行符。

cnt = 0
print str(cnt),
while True:
    cnt += 1
    print "\r" + str(cnt),

现在它将正确地重写行。

请注意,这是 Python 2.7,因此是print语句。

于 2014-11-27T16:25:56.227 回答
6

简易方法:

import sys
from time import sleep
import os

#print("\033[y coordinate;[x coordinateH Hello")
os.system('cls')
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H        []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)
于 2016-08-01T20:27:20.497 回答
3

如果您只想更新上一​​行,简单的方法:

import time
for i in range(20):
    print str(i) + '\r',
    time.sleep(1)
于 2009-01-22T00:37:07.717 回答
2

最简单的方法是使用两个 \r - 一个在开头,一个在结尾

for i in range(10000):
    print('\r'+str(round(i*100/10000))+'%  Complete\r'),

它会很快

于 2017-08-05T13:58:10.403 回答
1

在 Windows(python 3)上,它似乎可以工作(不直接使用 stdout):

import sys

for i in reversed(range(0,20)):
  time.sleep(0.1)
  if(i == 19):
    print(str(i), end='', file=sys.stdout)
  else:
    print("\r{0:{width}".format(str(i), width = w, fill = ' ', align = 'right'), end='', file=sys.stdout)
  sys.stdout.flush()
  w = len(str(i))

每次调用 print 函数时都会更新同一行。

此算法可以改进,但发布它是为了展示您可以做什么。您可以根据需要修改方法。

于 2012-03-03T05:13:01.137 回答
1

在 PyCharm 2020.3 和 Python 3.9 版上测试,为了覆盖书面打印输出,我使用以下内容:

from time import sleep

for x in range(10):
    print(f'\r {x}', end='')
    sleep(0.6)

这是我主要用于我的程序的代码。使用end='\r'将为我覆盖整个文本,忽略睡眠。

在实际场景中,我设置如下:

    def progress_callback(progress):
        print(f'\rDownloading File: {progress.dlable.file_name}  Progress: ' + '{0:.2f}%'.format(progress.percent), end='')
        # `return True` if the download should be canceled
        return False

    print('\nDownload complete!)

覆盖功能后的打印必须换行,否则之前的同一行将被覆盖。

于 2021-08-29T11:44:20.120 回答
1

感谢这里所有有用的答案。我需要这个:)

我发现 nosklo 的答案特别有用,但我希望通过将所需的输出作为参数传递来完全包含在函数中。另外,我真的不需要计时器,因为我希望在特定事件之后进行打印)。

这就是我的诀窍,我希望其他人觉得它有用:

import sys

def replace_cmd_line(output):
    """Replace the last command line output with the given output."""
    sys.stdout.write(output)
    sys.stdout.flush()
    sys.stdout.write('\r')
    sys.stdout.flush()
于 2017-01-19T22:14:49.987 回答
1

是的,这个问题是 11 年前提出的,但很酷。我喜欢即兴创作。附加到 nosklo 的答案:

import sys
import time

def restart_line():
    sys.stdout.write("\r")
    sys.stdout.flush()

string_one = "some data that is very long..."
sys.stdout.write(string_one)
sys.stdout.flush()

time.sleep(2)
restart_line()

string_two = "shorter data"
if len(string_two) < len(string_one):
    string_two = string_two+(" "*int((len(string_one)-len(string_two))))
    # This will overwrite the characters that would be left on the console

sys.stdout.write(string_two)
sys.stdout.flush()
于 2020-04-09T05:35:54.823 回答