Nếu tôi có mã sau:
for x in range(10):
print x
Tôi sẽ nhận được đầu ra của
1
2
etc..
Điều tôi muốn làm là thay vì in một dòng mới, tôi muốn thay thế giá trị trước đó và ghi đè nó bằng giá trị mới trên cùng một dòng.
Nếu tôi có mã sau:
for x in range(10):
print x
Tôi sẽ nhận được đầu ra của
1
2
etc..
Điều tôi muốn làm là thay vì in một dòng mới, tôi muốn thay thế giá trị trước đó và ghi đè nó bằng giá trị mới trên cùng một dòng.
Câu trả lời:
Một cách là sử dụng '\r'ký tự xuống dòng ( ) để trở về đầu dòng mà không chuyển sang dòng tiếp theo:
for x in range(10):
print '{0}\r'.format(x),
print
Dấu phẩy ở cuối câu lệnh in cho biết nó không chuyển sang dòng tiếp theo. Câu lệnh in cuối cùng chuyển sang dòng tiếp theo để lời nhắc của bạn không ghi đè đầu ra cuối cùng của bạn.
Bây giờ Python 2 là EOL, một câu trả lời Python 3 có ý nghĩa hơn. Đối với Python 3.5 trở về trước:
for x in range(10):
print('{}\r'.format(x), end="")
print()
Trong Python 3.6 trở lên, f-string đọc tốt hơn:
for x in range(10):
print(f'{x}\r', end="")
print()
%nhà điều hành bị phản đối. Về cơ bản, tất cả các chuỗi hiện có một phương thức định dạng . Trong trường hợp này, {0}nghĩa là "đối số đầu tiên đến format()" (đếm bắt đầu từ 0).
re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or '')sẽ cung cấp cho bạn chuỗi xóa từ đầu đến cuối dòng chính xác cho bất kỳ thiết bị đầu cuối nào mà người dùng có. Hãy nhớ khởi tạo cursesbằng một cái gì đó như curses.setupterm(fd=sys.stdout.fileno())và sử dụng sys.stdout.isatty()để đảm bảo rằng đầu ra của bạn không được chuyển hướng đến một tệp. Xem code.activestate.com/recipes/475116 để biết mô-đun Python đầy đủ với điều khiển con trỏ và hỗ trợ màu.
import curses; curses.setupterm(fd=sys.stdout.fileno()); print(hex(curses.tigetstr('cr')));Nó sẽ in các mã hex của chuỗi ký tự để đi đến đầu dòng.
Vì tôi đã kết thúc ở đây thông qua Google nhưng đang sử dụng Python 3, đây là cách điều này sẽ hoạt động trong Python 3:
for x in range(10):
print("Progress {:2.1%}".format(x / 10), end="\r")
Câu trả lời liên quan ở đây: Làm cách nào để chặn dòng mới sau câu lệnh in?
testingvà vòng lặp thứ hai của bạn in testđầu ra sau lần vượt qua thứ hai vẫn sẽ như vậy testing- bây giờ tôi thấy rằng @ Nagasaki45 đã chỉ ra điều này
print("\r", message, end="")
@Mike DeSimone câu trả lời có thể sẽ hoạt động hầu hết thời gian. Nhưng...
for x in ['abc', 1]:
print '{}\r'.format(x),
-> 1bc
Điều này là do '\r'chỉ quay trở lại đầu dòng nhưng không xóa đầu ra.
Nếu hỗ trợ POSIX là đủ cho bạn, phần sau sẽ xóa dòng hiện tại và để con trỏ ở đầu dòng:
print '\x1b[2K\r',
Nó sử dụng mã thoát ANSI để xóa dòng đầu cuối. Có thể tìm thấy thêm thông tin trong wikipedia và trong bài nói chuyện tuyệt vời này .
Giải pháp (không tốt lắm) mà tôi đã tìm thấy trông như thế này:
last_x = ''
for x in ['abc', 1]:
print ' ' * len(str(last_x)) + '\r',
print '{}\r'.format(x),
last_x = x
-> 1
Một ưu điểm là nó cũng sẽ hoạt động trên các cửa sổ.
Tôi đã có cùng một câu hỏi trước khi truy cập chủ đề này. Đối với tôi, sys.stdout.write chỉ hoạt động nếu tôi làm sạch bộ đệm đúng cách, tức là
for x in range(10):
sys.stdout.write('\r'+str(x))
sys.stdout.flush()
Không xả ra, kết quả chỉ được in ở cuối tập lệnh
stringvar.ljust(10,' ')trong trường hợp chuỗi có độ dài thay đổi.
Bỏ dòng mới và in \r.
print 1,
print '\r2'
hoặc viết thư cho stdout:
sys.stdout.write('1')
sys.stdout.write('\r2')
Thử cái này:
import time
while True:
print("Hi ", end="\r")
time.sleep(1)
print("Bob", end="\r")
time.sleep(1)
Nó đã làm việc cho tôi. Phần end="\r"đang làm cho nó ghi đè lên dòng trước đó.
CẢNH BÁO!
Nếu bạn in ra hi, sau đó in ra hellobằng cách sử dụng \r, bạn sẽ nhận được hillovì đầu ra được viết đè lên hai chữ cái trước đó. Nếu bạn in ra hivới khoảng trắng (không hiển thị ở đây), thì nó sẽ xuất ra hi. Để khắc phục điều này, hãy in ra các khoảng trắng bằng cách sử dụng \r.
Hi BobHi BobHi BobHi BobHi Bob. Python 3.7.1
\rlà ở phần đầu thay vì phần cuối.
Tôi không thể tìm thấy bất kỳ giải pháp nào trên trang này hoạt động cho IPython , nhưng một biến thể nhỏ trong giải pháp của @ Mike-Desimone đã thực hiện công việc: thay vì kết thúc dòng bằng ký tự xuống dòng, hãy bắt đầu dòng bằng ký tự xuống dòng:
for x in range(10):
print '\r{0}'.format(x),
Ngoài ra, phương pháp này không yêu cầu câu lệnh in thứ hai.
Điều này hoạt động trên Windows và python 3.6
import time
for x in range(10):
time.sleep(0.5)
print(str(x)+'\r',end='')
Câu trả lời được chấp nhận là không hoàn hảo . Dòng được in đầu tiên sẽ ở đó và nếu bản in thứ hai của bạn không bao phủ toàn bộ dòng mới, bạn sẽ kết thúc với văn bản rác.
Để minh họa sự cố, hãy lưu mã này dưới dạng tập lệnh và chạy nó (hoặc chỉ cần xem qua):
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))
Đầu ra sẽ giống như sau:
Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
Những gì hiệu quả với tôi là xóa dòng trước khi để lại một bản in vĩnh viễn. Vui lòng điều chỉnh vấn đề cụ thể của bạn:
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
Và bây giờ nó in như mong đợi:
Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
Đây là phiên bản "plug-and-play" gọn gàng hơn, hiệu quả hơn cho câu trả lời của @ Nagasaki45. Không giống như nhiều câu trả lời khác ở đây, nó hoạt động đúng với các chuỗi có độ dài khác nhau. Nó đạt được điều này bằng cách xóa dòng có nhiều khoảng trắng bằng chiều dài của dòng in cuối cùng. Cũng sẽ hoạt động trên 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
Đơn giản chỉ cần sử dụng nó như thế này:
for msg in ["Initializing...", "Initialization successful!"]:
print_statusline(msg)
time.sleep(1)
Thử nghiệm nhỏ này cho thấy rằng các dòng được xóa đúng cách, ngay cả với các độ dài khác nhau:
for i in range(9, 0, -1):
print_statusline("{}".format(i) * i)
time.sleep(0.5)
Tôi hơi ngạc nhiên là không ai sử dụng ký tự xóa lùi. Đây là một trong những sử dụng nó.
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) Đây là những gì đã làm việc cho tôi. Nếu bạn chỉ sử dụng \ 010 thì nó sẽ để lại các ký tự, vì vậy tôi đã chỉnh sửa nó một chút để đảm bảo nó ghi đè lên những gì ở đó. Điều này cũng cho phép bạn có một cái gì đó trước mục in đầu tiên và chỉ loại bỏ chiều dài của mục đó.
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
Thêm một câu trả lời dựa trên các câu trả lời trước đó.
Nội dung của 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()
Cách sử dụng tập lệnh:
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)
Đây là giải pháp của tôi! Windows 10, Python 3.7.1
Tôi không chắc tại sao mã này hoạt động, nhưng nó xóa hoàn toàn dòng gốc. Tôi đã tổng hợp nó từ những câu trả lời trước. Các câu trả lời khác sẽ chỉ trả lại dòng về đầu, nhưng nếu bạn có một dòng ngắn hơn sau đó, nó sẽ trông lộn xộn như hellobiến thành 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)
Đầu ra - Mỗi dòng sẽ được viết lại mà không có bất kỳ văn bản cũ nào hiển thị:
SCRAPING COMPLETE: selenagomez
Dòng tiếp theo (được viết lại hoàn toàn trên cùng một dòng):
SCRAPING COMPLETE: beyonce