2009-01-21 69 views
15

在Unix上,我可以使用\ r(回車)或\ b(退格)打印shell中已經可見的文本(即再次覆蓋當前行)。如何在命令行應用程序的當前行上打印?

我可以通過Python腳本在Windows命令行中實現相同效果嗎?

我試過curses模塊,但它似乎沒有在Windows上可用。

+0

我[提問](http://stackoverflow.com/questions/51212/how-to-write-a-download-progress-indicator-in-python)大約一個Python下載進度指標可能會有所幫助。 – cschol 2009-01-21 13:55:28

回答

23

是:

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() 
+0

真棒,對於那些想知道的:適用於2.7 – 2016-06-08 11:57:23

+3

如果第二個數據比第一個數據短,第一個數據的字符留在控制檯上 – Hilal 2016-08-09 12:19:01

2

,如果你只是想更新前一行簡單的方法:

import time 
for i in range(20): 
    print str(i) + '\r', 
    time.sleep(1) 
1

在Windows(Python 3中),似乎工作(沒有標準輸出直接使用):

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)) 

每次打印函數被調用時都會更新相同的行。

該算法可以改進,但它被張貼來顯示你可以做什麼。您可以根據需要修改該方法。

11
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的筆記本,就像這樣:

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

+1

ipython筆記本/ jupyter是我一直在尋找的! – dmeu 2015-08-13 14:28:43

4

我知道這是老了,但我想告訴我的版本(它的作品在我的電腦在cmd中,但不在空閒中)重寫Python 3中的一行:

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

編輯: 它適用於Windows和Ubuntu上

5

我剛剛有這個問題。即使在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 

當你\r,你去行的開頭。但是你已經在線的開始。

修正是爲了避免打印\n字符,因此您的光標位於同一行,並且\r會正確覆蓋文本。你可以用print 'text',來做到這一點。逗號禁止打印換行符。

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

現在它會正確地重寫行。

請注意,這是Python 2.7,因此是print聲明。

5

簡單的方法:)

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) 
0

感謝您對這裏的傢伙的所有有用的答案。我需要這個:)

我發現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() 
+0

最後你只需要一個flush()。我不確定`sys.stdout.write(output +'\ r')`會比兩個方法調用(因爲爲字符串分配內存,複製,GC)快得多,因此保持它們分離可能是好的。 – 2017-01-25 09:47:24

1

最簡單的方法是使用兩個\ r - 一個開頭,一個在結尾

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

它會很快

相關問題