在 Unix 上,我可以使用\r
(carriage return) 或\b
(backspace) 来覆盖 shell 中的当前行(打印已经可见的文本)。
我可以通过 Python 脚本在 Windows 命令行中实现相同的效果吗?
我尝试了 curses 模块,但它似乎在 Windows 上不可用。
在 Unix 上,我可以使用\r
(carriage return) 或\b
(backspace) 来覆盖 shell 中的当前行(打印已经可见的文本)。
我可以通过 Python 脚本在 Windows 命令行中实现相同的效果吗?
我尝试了 curses 模块,但它似乎在 Windows 上不可用。
是的:
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()
我知道这很旧,但我想告诉我的版本(它可以在我的电脑上的 cmd 中工作,但不能在空闲时)覆盖 Python 3 中的一行:
>>> from time import sleep
>>> for i in range(400):
>>> print("\r" + str(i), end="")
>>> sleep(0.5)
编辑: 它适用于 Windows 和 Ubuntu
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)
我刚遇到这个问题。即使在 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
语句。
简易方法:
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)
如果您只想更新上一行,简单的方法:
import time
for i in range(20):
print str(i) + '\r',
time.sleep(1)
最简单的方法是使用两个 \r - 一个在开头,一个在结尾
for i in range(10000):
print('\r'+str(round(i*100/10000))+'% Complete\r'),
它会很快
在 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 函数时都会更新同一行。
此算法可以改进,但发布它是为了展示您可以做什么。您可以根据需要修改方法。
在 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!)
覆盖功能后的打印必须换行,否则之前的同一行将被覆盖。
感谢这里所有有用的答案。我需要这个:)
我发现 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()
是的,这个问题是 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()