In đến cùng một dòng chứ không phải một dòng mới trong python


85

Về cơ bản tôi muốn làm ngược lại những gì anh chàng này đã làm ... hehe.

Python Script: In dòng mới mỗi lần để trình bao thay vì cập nhật dòng hiện có

Tôi có một chương trình đang cho tôi biết nó còn bao xa.

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete"

Vì vậy, nếu len (some_list) là 50, tôi sẽ in dòng cuối cùng đó 50 lần. Tôi muốn in một dòng và tiếp tục cập nhật dòng đó. Tôi biết tôi biết đây có lẽ là câu hỏi hay nhất mà bạn sẽ đọc cả ngày. Tôi chỉ không thể tìm ra bốn từ tôi cần đưa vào google để có câu trả lời.

Cập nhật! Tôi đã thử đề xuất của mvds mà SEEMED đúng. Mã mới

print percent_complete,"           \r",

Phần trăm hoàn thành chỉ là một chuỗi (tôi đã trừu tượng hóa lần đầu tiên bây giờ tôi đang cố gắng hiểu theo nghĩa đen). Kết quả bây giờ là nó chạy chương trình, không in BẤT KỲ ĐIỀU GÌ cho đến khi chương trình kết thúc, và sau đó in "hoàn thành 100 phần trăm" trên một và chỉ một dòng.

Nếu không có dấu xuống dòng (nhưng có dấu phẩy, một nửa gợi ý của mvds), nó không in gì cho đến cuối. Và sau đó in:

0 percent complete     2 percent complete     3 percent complete     4 percent complete    

Và như thế. Vì vậy, bây giờ vấn đề mới là với dấu phẩy nó không in cho đến khi chương trình kết thúc.

Với dấu xuống dòng và không có dấu phẩy, nó hoạt động giống hệt như với không.


Bạn cũng có thể muốn kiểm tra sys.stdout.isatty()để không nói ra những điều này khi không chạy trong thiết bị đầu cuối.
mvds

Tôi đang chạy điều này từ một thiết bị đầu cuối ... mặc dù vậy, ý nghĩ tốt. Tôi chắc rằng một lúc nào đó tôi sẽ cần đến điều đó.
chriscauley

1
nền, btw, trong một số ngôn ngữ, \ n (mà bây giờ chúng tôi bỏ qua) đóng vai trò như một tín hiệu ngầm để chuyển sang stdout. Nếu không, rất nhiều người sẽ bối rối.
mvds

Câu trả lời:


85

Nó được gọi là dấu xuống dòng, hoặc \r

Sử dụng

print i/len(some_list)*100," percent complete         \r",

Dấu phẩy ngăn việc in thêm dòng mới. (và các khoảng trắng sẽ giữ cho dòng rõ ràng so với đầu ra trước đó)

Ngoài ra, đừng quên kết thúc bằng dấu print ""để nhận được ít nhất một dòng mới cuối cùng!


12
Chỉ cần đảm bảo rằng bạn luôn in cùng một lượng dữ liệu (hoặc nhiều hơn bất kỳ bản in nào trước đó) vào dòng, nếu không, bạn sẽ bị lỗi ở cuối dòng.
Nicholas Knight

Gần quá ... Tôi sẽ cập nhật câu hỏi với kết quả của việc này.
chriscauley

2
@dustynachos: Hì, quên mất nếp nhăn đó. Xem câu hỏi về bộ đệm đầu ra Python: stackoverflow.com/questions/107705/python-output-buffering
Nicholas Knight

1
@dustynachos: (hoặc chỉ sử dụng sys.stdout.flush () sau mỗi lần gọi in, điều đó thực sự có thể tốt hơn nếu bạn không quan tâm đến bộ đệm đầu ra cho phần còn lại của chương trình của mình)
Nicholas Knight

2
điều này không hiệu quả với tôi. Tôi thực sự đã thử điều này nhiều lần và nó chưa bao giờ hiệu quả với tôi. Tôi đang sử dụng iterm2 trên máy mac, nhưng hầu như lúc nào tôi cũng sử dụng máy chủ linux. Tôi chưa bao giờ tìm thấy một phương pháp để làm điều này mà thực sự hiệu quả.
bgenchel

35

Đối với tôi, những gì hiệu quả là sự kết hợp giữa câu trả lời của Remi và siriusd:

from __future__ import print_function
import sys

print(str, end='\r')
sys.stdout.flush()

33

Từ python 3.x, bạn có thể làm:

print('bla bla', end='')

(cũng có thể được sử dụng trong Python 2.6 hoặc 2.7 bằng cách đặt from __future__ import print_functionở đầu tập lệnh / mô-đun của bạn)

Ví dụ về thanh tiến trình của bảng điều khiển Python:

import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    n=0
    while n<total:
        done = '#'*(n+1)
        todo = '-'*(total-n-1)
        s = '<{0}>'.format(done+todo)
        if not todo:
            s+='\n'        
        if n>0:
            s = '\r'+s
        print(s, end='')
        yield n
        n+=1

# example for use of status generator
for i in range_with_status(10):
    time.sleep(0.1)

\ R cũng xuất hiện để thêm một dòng mới
fccoelho

2
điều này loại bỏ dòng mới, nhưng không cho phép ghi đè, mà tôi nghĩ đó là những gì tác giả muốn.
bgenchel

1
@bgenchel được sử dụng với '\ r' (như trong mã mẫu) nó thực hiện chính xác những gì OP muốn
Milo Wielondek

19

Trong Python 3.3+, bạn không cần sys.stdout.flush(). print(string, end='', flush=True)làm.

Vì thế

print('foo', end='')
print('\rbar', end='', flush=True)

sẽ ghi đè 'foo' bằng 'bar'.


2
Nó hoạt động, miễn là văn bản in kết thúc bằng a "\r".
Bli

13

cho Console có thể bạn sẽ cần

sys.stdout.flush()

để buộc cập nhật. Tôi nghĩ rằng việc sử dụng ,trong bản in sẽ chặn stdout xả và bằng cách nào đó nó sẽ không cập nhật


Terminator chỉ làm mới dòng sau mỗi 30 giây khi sử dụng print ("...", end = '\ r') cho tôi trừ khi tôi chạy lệnh này ngay sau câu lệnh print. Cảm ơn
Bryce Guinta

4

Cuối trò chơi - nhưng vì không có câu trả lời nào phù hợp với tôi (tôi đã không thử tất cả chúng) và tôi đã tìm thấy câu trả lời này nhiều lần trong tìm kiếm của mình ... Trong python 3, giải pháp này khá thanh lịch và tôi tin rằng thực hiện chính xác những gì tác giả đang tìm kiếm, nó cập nhật một tuyên bố duy nhất trên cùng một dòng. Lưu ý, bạn có thể phải làm điều gì đó đặc biệt nếu đường dây co lại thay vì dài ra (chẳng hạn như có thể làm cho dây có độ dài cố định với khoảng cách đệm ở cuối)

if __name__ == '__main__':
    for i in range(100):
        print("", end=f"\rPercentComplete: {i} %")
        time.sleep(0.2)

tùy chọn đơn giản và sạch sẽ nhất cho python => 3.6
DaveR

3

Điều này phù hợp với tôi, đã hack nó một lần để xem có khả thi không, nhưng chưa bao giờ thực sự được sử dụng trong chương trình của tôi (GUI đẹp hơn rất nhiều):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
    print clear+f % (i*100//123),
    time.sleep(0.4)
raw_input('\nDone')

2
import time
import sys


def update_pct(w_str):
    w_str = str(w_str)
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(" " * len(w_str))
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(w_str)
    sys.stdout.flush()

for pct in range(0, 101):
    update_pct("{n}%".format(n=str(pct)))
    time.sleep(0.1)

\bsẽ di chuyển vị trí của con trỏ trở lại một không gian
Vì vậy, chúng tôi di chuyển nó sao lưu tất cả các cách để các đầu dòng
Chúng tôi sau đó không gian ghi để xóa dòng hiện tại - như chúng ta viết không gian di chuyển con trỏ về phía trước / phải bởi một
Vì vậy, sau đó chúng tôi có để di chuyển con trỏ trở lại đầu dòng trước khi chúng tôi viết dữ liệu mới

Đã thử nghiệm trên Windows cmd bằng Python 2.7


1

Hãy thử nó như thế này:

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete",

(Có dấu phẩy ở cuối.)


Điều này chỉ nối văn bản mới với văn bản cũ (tương tự về chức năng nhưng xấu xí).
chriscauley

1

Nếu bạn đang sử dụng Spyder, các dòng chỉ in liên tục với tất cả các giải pháp trước đó. Một cách để tránh điều đó là sử dụng:

for i in range(1000):
    print('\r' + str(round(i/len(df)*100,1)) + '% complete', end='')
    sys.stdout.flush()

Đây là giải pháp làm việc duy nhất đối với tôi (Python 3.8, Windows, PyCharm).
z33k

0

Dựa trên câu trả lời của Remi để Python 2.7+sử dụng:

from __future__ import print_function
import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    import sys
    n = 0
    while n < total:
        done = '#' * (n + 1)
        todo = '-' * (total - n - 1)
        s = '<{0}>'.format(done + todo)
        if not todo:
            s += '\n'
        if n > 0:
            s = '\r' + s
        print(s, end='\r')
        sys.stdout.flush()
        yield n
        n += 1


# example for use of status generator
for i in range_with_status(50):
    time.sleep(0.2)

0

Đối với Python 3.6+và cho bất kỳ listthay vì chỉ ints, cũng như sử dụng toàn bộ chiều rộng của cửa sổ bảng điều khiển của bạn và không vượt qua một dòng mới, bạn có thể sử dụng như sau:

lưu ý: xin được thông báo rằng chức năng get_console_with()sẽ chỉ hoạt động trên các hệ thống dựa trên Linux, và do đó bạn phải viết lại nó để hoạt động trên Windows.

import os
import time

def get_console_width():
    """Returns the width of console.

    NOTE: The below implementation works only on Linux-based operating systems.
    If you wish to use it on another OS, please make sure to modify it appropriately.
    """
    return int(os.popen('stty size', 'r').read().split()[1])


def range_with_progress(list_of_elements):
    """Iterate through list with a progress bar shown in console."""

    # Get the total number of elements of the given list.
    total = len(list_of_elements)
    # Get the width of currently used console. Subtract 2 from the value for the
    # edge characters "[" and "]"
    max_width = get_console_width() - 2
    # Start iterating over the list.
    for index, element in enumerate(list_of_elements):
        # Compute how many characters should be printed as "done". It is simply
        # a percentage of work done multiplied by the width of the console. That
        # is: if we're on element 50 out of 100, that means we're 50% done, or
        # 0.5, and we should mark half of the entire console as "done".
        done = int(index / total * max_width)
        # Whatever is left, should be printed as "unfinished"
        remaining = max_width - done
        # Print to the console.
        print(f'[{done * "#"}{remaining * "."}]', end='\r')
        # yield the element to work with it
        yield element
    # Finally, print the full line. If you wish, you can also print whitespace
    # so that the progress bar disappears once you are done. In that case do not
    # forget to add the "end" parameter to print function.
    print(f'[{max_width * "#"}]')


if __name__ == '__main__':
    list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    for e in range_with_progress(list_of_elements):
        time.sleep(0.2)


0

Nếu bạn đang sử dụng Python 3 thì điều này là dành cho bạn và nó thực sự hoạt động.

print(value , sep='',end ='', file = sys.stdout , flush = False)

0

Đối với Python 3+

for i in range(5):
    print(str(i) + '\r', sep='', end ='', file = sys.stdout , flush = False)

0

Tôi chỉ tự tìm ra điều này để hiển thị đếm ngược nhưng nó cũng sẽ hoạt động theo tỷ lệ phần trăm.

import time
#Number of seconds to wait
i=15
#Until seconds has reached zero
while i > -1:
    #Ensure string overwrites the previous line by adding spaces at end
    print("\r{} seconds left.   ".format(i),end='')
        time.sleep(1)
        i-=1
    print("") #Adds newline after it's done

Miễn là bất cứ thứ gì đứng sau '/ r' có cùng độ dài hoặc dài hơn (bao gồm cả dấu cách) so với chuỗi trước đó, thì nó sẽ ghi đè lên trên cùng một dòng. Chỉ cần đảm bảo rằng bạn bao gồm end = '' nếu không nó sẽ in ra một dòng mới. Hy vọng rằng sẽ giúp!


0

đối với đối tượng "pega" cung cấp giá trị trả về StartRunning (), StopRunning (), boolean getIsRunning () và số nguyên getProgress100 () trong phạm vi từ 0 đến 100, điều này cung cấp thanh tiến trình văn bản trong khi chạy ...

now = time.time()
timeout = now + 30.0
last_progress = -1

pega.StartRunning()

while now < timeout and pega.getIsRunning():
    time.sleep(0.5)
    now = time.time()

    progress = pega.getTubProgress100()
    if progress != last_progress:
        print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", end='', flush=True)
        last_progress = progress

pega.StopRunning()

progress = pega.getTubProgress100()
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", flush=True)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.