簡體   English   中英

如何覆蓋以前的打印到標准輸出?

[英]How to overwrite the previous print to stdout?

如果我有以下代碼:

for x in range(10):
     print(x)

我會得到 output

1
2
etc..

我想做的不是打印換行符,而是想替換以前的值並在同一行上用新值覆蓋它。

簡單版<\/h1>

一種方法是使用回車 ( '\\r'<\/code> ) 字符返回到行首而不前進到下一行。

蟒蛇 3<\/h3>
 Python 2.7 向前兼容<\/h3>
from __future__ import print_function for x in range(10): print(x, end='\\r') print()<\/code><\/pre>

蟒蛇 2.7<\/h3>
 for x in range(10): print '{}\\r'.format(x), print<\/code><\/pre>

Python 2.0-2.6<\/h3>
 for x in range(10): print '{0}\\r'.format(x), print<\/code><\/pre>

在后兩種情況下(僅限 Python 2),print 語句末尾的逗號告訴它不要轉到下一行。 最后一個打印語句前進到下一行,因此您的提示不會覆蓋您的最終輸出。

線路清潔<\/h1>

如果不能保證新的文本行不短於現有行,那么只需添加一個“清除到行尾”的轉義序列, '\\x1b[1K'<\/code> ( '\\x1b'<\/code> = ESC ):

由於我最終通過 Google 來到這里,但我使用的是 Python 3,以下是它在 Python 3 中的工作方式:

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

@Mike DeSimone 的回答<\/a>可能大部分時間都有效。 但...

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

-> 1bc

在訪問此線程之前,我有同樣的問題。 對我來說 sys.stdout.write 只有在我正確刷新緩沖區時才有效,即

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

不刷新,結果僅在腳本結束時打印

禁止換行並打印\\r

print 1,
print '\r2'

或寫入標准輸出:

sys.stdout.write('1')
sys.stdout.write('\r2')
for x in range(10):
    time.sleep(0.5) # shows how its working
    print("\r {}".format(x), end="")

time.sleep(0.5) 用於顯示如何擦除先前的輸出並在打印消息開始時打印新輸出“\\r”,它將在新輸出之前擦除先前的輸出。

試試這個:

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

它對我有用。 end="\\r"部分使其覆蓋上一行。

警告!

如果您打印出hi ,然后使用\\r打印出hello ,您將得到hillo ,因為輸出覆蓋了前兩個字母。 如果你用空格打印出hi (這里沒有顯示),那么它將輸出hi 要解決此問題,請使用\\r打印出空格。

這是@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

我無法讓此頁面上的任何解決方案適用於IPython<\/strong> ,但@Mike-Desimone 的解決方案的細微變化完成了這項工作:不是用回車終止行,而是用回車開始<\/em>行:

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

這適用於 Windows 和 python 3.6

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

接受的答案並不完美 第一次打印的行將保留在那里,如果您的第二次打印沒有覆蓋整個新行,您將得到垃圾文本。

為了說明問題,將此代碼保存為腳本並運行它(或只是看看):

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%

我有點驚訝沒有人使用退格字符。 這是使用它的一個。

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

我使用以下方法創建了一個加載器:

for i in range(10):
    print(i*'.', end='\r')

這是我的解決方案! 視窗 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

(Python3)這對我有用。 如果你只使用 \\010 那么它會留下字符,所以我對其進行了一些調整以確保它覆蓋了那里的內容。 這也允許您在第一個打印項目之前有一些東西,並且只刪除項目的長度。

print("Here are some strings: ", end="")
items = ["abcd", "abcdef", "defqrs", "lmnop", "xyz"]
for item in items:
    print(item, end="")
    for i in range(len(item)): # only moving back the length of the item
        print("\010 \010", end="") # the trick!
        time.sleep(0.2) # so you can see what it's doing

根據之前的答案再做一個答案。

pbar.py 的內容:import sys、shutil、datetime

last_line_is_progress_bar=False


def print2(print_string):
    global last_line_is_progress_bar
    if last_line_is_progress_bar:
        _delete_last_line()
        last_line_is_progress_bar=False
    print(print_string)


def _delete_last_line():
    sys.stdout.write('\b\b\r')
    sys.stdout.write(' '*shutil.get_terminal_size((80, 20)).columns)
    sys.stdout.write('\b\r')
    sys.stdout.flush()


def update_progress_bar(current, total):
    global last_line_is_progress_bar
    last_line_is_progress_bar=True

    completed_percentage = round(current / (total / 100))
    current_time=datetime.datetime.now().strftime('%m/%d/%Y-%H:%M:%S')
    overhead_length = len(current_time+str(current))+13
    console_width = shutil.get_terminal_size((80, 20)).columns - overhead_length
    completed_width = round(console_width * completed_percentage / 100)
    not_completed_width = console_width - completed_width
    sys.stdout.write('\b\b\r')

    sys.stdout.write('{}> [{}{}] {} - {}% '.format(current_time, '#'*completed_width, '-'*not_completed_width, current,
                                        completed_percentage),)
    sys.stdout.flush()

最好覆蓋整行,否則如果新行較短,新行將與舊行混合。

import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
    print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
    time.sleep(1)

必須在 Windows 上使用columns - 1

這對我有用,在 Windows 中使用 Spyder 中的 Python 3.7.9:

from IPython.display import clear_output
from time import sleep

def print_and_overwrite(text):
    '''Remember to add print() after the last print that you want to overwrite.'''
    clear_output(wait=True)
    print(text, end='\r')

for i in range(15):
    #I print the results backwards (from 15 to 1), to test shorter strings
    message = "Iteration %d out of 15" %(15-i)
    print_and_overwrite(message)
    sleep(0.5)

print() #This stops the overwriting
print("This will be on a new line")

無論如何,如果有人想套印(清除)以前在標准輸出中打印的許多,那么這個答案應該對他有幫助。 (感謝 Thijmen Dam 的好文章覆蓋以前打印的行

在 ANSI 控制台中,您可以使用特殊序列:

\033[1A\033[K

他們首先舉起 cursor,其次 - 完全擦除一行。

清除控制台的示例 (Python 3):

LINE_UP = '\033[1A'
LINE_CLEAR = '\033[K'
CONSOLE_HEIGHT = 24 #lines

def clear_console():
    for a in range(CONSOLE_HEIGHT):
        print(LINE_UP, end=LINE_CLEAR, flush=True)

或者最終簡單地(將清除屏幕並將 cursor 移動到 0,0):

print('\033[2J', end='', flush=True)

如果你只想定位 cursor,那么使用這個:

print('\033[<L>;<C>f', end='', flush=True)

其中<L><C>對應的是Line和Column。

ANSI轉義序列的少數參考

這里有一個簡單的代碼,對您有用!

import sys
import time

for i in range(10):
    sys.stdout.write("\r" + i)
    sys.stdout.flush()
    time.sleep(1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM