Gdybym miał następujący kod:
for x in range(10):
print x
Otrzymałbym wyjście
1
2
etc..
Chciałbym zamiast drukować znak nowej linii, chcę zastąpić poprzednią wartość i nadpisać ją nową wartością w tym samym wierszu.
Gdybym miał następujący kod:
for x in range(10):
print x
Otrzymałbym wyjście
1
2
etc..
Chciałbym zamiast drukować znak nowej linii, chcę zastąpić poprzednią wartość i nadpisać ją nową wartością w tym samym wierszu.
Odpowiedzi:
Jednym ze sposobów jest użycie znaku powrotu karetki ( '\r'), aby powrócić na początek wiersza bez przechodzenia do następnego wiersza:
for x in range(10):
print '{0}\r'.format(x),
print
Przecinek na końcu instrukcji print mówi mu, aby nie przechodził do następnego wiersza. Ostatnia instrukcja print przechodzi do następnego wiersza, więc znak zachęty nie nadpisze końcowego wyniku.
Teraz, gdy Python 2 to EOL, odpowiedź w Pythonie 3 ma większy sens. Dla Pythona 3.5 i wcześniejszych:
for x in range(10):
print('{}\r'.format(x), end="")
print()
W Pythonie 3.6 i nowszych f-stringi czytają lepiej:
for x in range(10):
print(f'{x}\r', end="")
print()
%operator jest zalecane. Zasadniczo wszystkie ciągi mają teraz metodę formatowania . W tym przypadku {0}oznacza „pierwszy argument do format()” (liczenie zaczyna się od 0).
re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or '')poda ci poprawny ciąg wymazywania do końca linii dla dowolnego terminala, który ma użytkownik. Pamiętaj, aby zainicjować cursescoś podobnego curses.setupterm(fd=sys.stdout.fileno())i użyć, sys.stdout.isatty()aby upewnić się, że dane wyjściowe nie są przekierowywane do pliku. Zobacz code.activestate.com/recipes/475116, aby zapoznać się z pełnym modułem Pythona z kontrolą kursora i obsługą kolorów.
import curses; curses.setupterm(fd=sys.stdout.fileno()); print(hex(curses.tigetstr('cr')));Powinien wydrukować kody szesnastkowe sekwencji znaków, aby przejść na początek wiersza.
Ponieważ znalazłem się tutaj przez Google, ale używam Pythona 3, oto jak to działałoby w Pythonie 3:
for x in range(10):
print("Progress {:2.1%}".format(x / 10), end="\r")
Powiązana odpowiedź tutaj: Jak mogę pominąć znak nowej linii po instrukcji print?
testingi druga pętla wydrukuje testwynik po drugim przebiegu nadal będzie testing- teraz widzę, że @ Nagasaki45 zwrócił na to uwagę
print("\r", message, end="")
@Mike DeSimone odpowiedź prawdopodobnie będzie działać przez większość czasu. Ale...
for x in ['abc', 1]:
print '{}\r'.format(x),
-> 1bc
Dzieje się tak, ponieważ '\r'jedyny wraca na początek wiersza, ale nie czyści wyjścia.
Jeśli obsługa POSIX jest dla Ciebie wystarczająca, poniższe czynności wyczyściłyby bieżący wiersz i pozostawił kursor na jego początku:
print '\x1b[2K\r',
Używa kodu ucieczki ANSI, aby wyczyścić linię terminala. Więcej informacji można znaleźć na Wikipedii oraz w tym wspaniałym wykładzie .
(Niezbyt dobre) rozwiązanie, które znalazłem, wygląda następująco:
last_x = ''
for x in ['abc', 1]:
print ' ' * len(str(last_x)) + '\r',
print '{}\r'.format(x),
last_x = x
-> 1
Zaletą jest to, że będzie działać również w systemie Windows.
Miałem to samo pytanie przed odwiedzeniem tego wątku. U mnie sys.stdout.write działał tylko wtedy, gdy prawidłowo opróżnię bufor tj
for x in range(10):
sys.stdout.write('\r'+str(x))
sys.stdout.flush()
Bez opróżniania wynik jest drukowany tylko na końcu skryptu
stringvar.ljust(10,' ')w przypadku łańcuchów o zmiennej długości.
Pomiń znak nowej linii i drukuj \r.
print 1,
print '\r2'
lub napisz na stdout:
sys.stdout.write('1')
sys.stdout.write('\r2')
Spróbuj tego:
import time
while True:
print("Hi ", end="\r")
time.sleep(1)
print("Bob", end="\r")
time.sleep(1)
U mnie to zadziałało. end="\r"Część czyni go nadpisać poprzednią linię.
OSTRZEŻENIE!
Jeśli wydrukujesz hi, a następnie wydrukujesz za hellopomocą \r, otrzymasz, hilloponieważ wynik został napisany na poprzednich dwóch literach. Jeśli wydrukujesz hize spacjami (które nie pojawiają się tutaj), to wyjdzie hi. Aby to naprawić, wydrukuj spacje za pomocą \r.
Hi BobHi BobHi BobHi BobHi Bob. Python 3.7.1
\rjest na początku zamiast na końcu.
Nie mogłem uzyskać żadnego z rozwiązań na tej stronie do pracy z IPythonem , ale niewielka zmiana w rozwiązaniu @ Mike-Desimone załatwiła sprawę: zamiast kończyć wiersz znakiem powrotu karetki, rozpocznij wiersz od powrotu karetki:
for x in range(10):
print '\r{0}'.format(x),
Ponadto to podejście nie wymaga drugiej instrukcji print.
for x in range(10):
time.sleep(0.5) # shows how its working
print("\r {}".format(x), end="")
time.sleep (0.5) pokazuje, jak poprzedni wynik jest kasowany, a nowy wydruk jest drukowany "\ r". Kiedy jest na początku komunikatu drukowania, usunie poprzednie wyjście przed nowym wyjściem.
Działa to w systemie Windows i Pythonie 3.6
import time
for x in range(10):
time.sleep(0.5)
print(str(x)+'\r',end='')
Przyjęta odpowiedź nie jest doskonała . Linia, która została wydrukowana jako pierwsza, pozostanie tam, a jeśli twój drugi wydruk nie pokryje całej nowej linii, skończysz ze śmieciowym tekstem.
Aby zilustrować problem, zapisz ten kod jako skrypt i uruchom go (lub po prostu spójrz):
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))
Wynik będzie wyglądał mniej więcej tak:
Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
To, co działa dla mnie, to wyczyszczenie linii przed pozostawieniem trwałego wydruku. Zapraszam do dostosowania się do konkretnego problemu:
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
A teraz drukuje zgodnie z oczekiwaniami:
Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
Oto bardziej przejrzysta, bardziej „plug-and-play” wersja odpowiedzi @ Nagasaki45. W przeciwieństwie do wielu innych odpowiedzi tutaj, działa poprawnie ze sznurkami o różnych długościach. Osiąga to poprzez wyczyszczenie wiersza z taką samą liczbą spacji, jak długość ostatniego wydrukowanego wiersza. Działa również w systemie 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
Po prostu użyj tego w ten sposób:
for msg in ["Initializing...", "Initialization successful!"]:
print_statusline(msg)
time.sleep(1)
Ten mały test pokazuje, że linie są usuwane prawidłowo, nawet przy różnych długościach:
for i in range(9, 0, -1):
print_statusline("{}".format(i) * i)
time.sleep(0.5)
Jestem trochę zaskoczony, że nikt nie używa znaku backspace. Oto jeden, który go używa.
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')
sys.stdout.flush()
(Python3) To właśnie zadziałało dla mnie. Jeśli użyjesz tylko \ 010, to pozostawi znaki, więc poprawiłem go trochę, aby upewnić się, że nadpisuje to, co tam było. Pozwala to również mieć coś przed pierwszym drukowanym elementem i usunąć tylko długość elementu.
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
Jeszcze jedna odpowiedź oparta na wcześniejszych odpowiedziach.
Zawartość 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()
Wykorzystanie skryptu:
import time
from pbar import update_progress_bar, print2
update_progress_bar(45,200)
time.sleep(1)
update_progress_bar(70,200)
time.sleep(1)
update_progress_bar(100,200)
time.sleep(1)
update_progress_bar(130,200)
time.sleep(1)
print2('some text that will re-place current progress bar')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
print('\n') # without \n next line will be attached to the end of the progress bar
print('built in print function that will push progress bar one line up')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
Oto moje rozwiązanie! Windows 10, Python 3.7.1
Nie jestem pewien, dlaczego ten kod działa, ale całkowicie usuwa oryginalny wiersz. Skompilowałem to na podstawie poprzednich odpowiedzi. Inne odpowiedzi po prostu przywróciłyby linię na początek, ale gdybyś miał później krótszą linię, wyglądałaby na pomieszaną, jakby hellozamieniła się w 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)
Wyjście - każda linia zostanie przepisana bez żadnego starego tekstu pokazującego:
SCRAPING COMPLETE: selenagomez
Następna linia (przepisana całkowicie w tej samej linii):
SCRAPING COMPLETE: beyonce
Lepiej jest nadpisać całą linię, w przeciwnym razie nowa linia będzie mieszać się ze starymi, jeśli nowa linia będzie krótsza.
import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
time.sleep(1)
Musiał użyć columns - 1w systemie Windows.