Yeni bir satır değil de aynı satıra yazdırılsın mı?


89

Temelde bu adamın yaptığının tam tersini yapmak istiyorum ... hehe.

Python Komut Dosyası: Mevcut satırı güncellemek yerine her seferinde kabuk için yeni satır yazdırın

Bana ne kadar ilerlediğini söyleyen bir programım var.

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

Yani eğer len (some_list) 50 olsaydı, o son satırı 50 kez yazdırırdım. Bir satır yazdırmak ve o satırı güncellemeye devam etmek istiyorum. Bunun muhtemelen bütün gün okuyacağın en kötü soru olduğunu biliyorum. Cevabı almak için google'a koymam gereken dört kelimeyi çözemiyorum.

Güncelleme! Mvds'nin doğru görülen önerisini denedim. Yeni kod

print percent_complete,"           \r",

Tamamlanma yüzdesi sadece bir dizedir (ilk kez soyutluyordum, şimdi gerçek olmaya çalışıyorum). Şimdi sonuç, programı çalıştırması, program bitene kadar HİÇBİR ŞEY yazdırmaması ve ardından bir ve yalnızca bir satıra "yüzde 100 tamamlandı" yazmasıdır.

Satır başı olmadan (ancak virgülle, mvds'nin önerisinin yarısı) sonuna kadar hiçbir şey yazdırmaz. Ve sonra şunu yazdırır:

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

Ve bunun gibi. Şimdi yeni sorun, virgülle program bitene kadar yazılmamasıdır.

Satır başı ile ve virgül yokken hiçbiriyle aynı şekilde davranmaz.


sys.stdout.isatty()Bir terminalde çalışmadığınızda bunları tükürmemek için kontrol etmek isteyebilirsiniz .
mvds

Bunu bir terminalden çalıştırıyorum ... yine de iyi fikir. Eminim bir noktada buna ihtiyacım olacak.
chriscauley

1
arka plan, btw, birkaç dilde \ n (şimdi atladığımız), stdout'u temizlemek için örtük bir sinyal olarak hizmet ediyor. Aksi takdirde birçok insanın kafası karışacaktır.
mvds

Yanıtlar:


86

Buna satır başı veya \r

Kullanım

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

Virgül, baskının yeni satır eklemesini engeller. (ve boşluklar, satırı önceki çıktıdan uzak tutacaktır)

Ayrıca, print ""en azından son halini alan bir yeni satır almak için a ile sonlandırmayı unutmayın !


12
Sadece satıra her zaman aynı miktarda (veya önceki herhangi bir baskıdan daha fazla) veri yazdırdığınızdan emin olun, aksi takdirde sonunda pürüzler yaşarsınız.
Nicholas Şövalye

Çok yakın ... Soruyu bunun sonucuyla güncelleyeceğim.
chriscauley

2
@dustynachos: Heh, o kırışıklığı unuttum. Python Çıktı Tamponlama sorusuna bakın: stackoverflow.com/questions/107705/python-output-buffering
Nicholas Knight

1
@dustynachos: (Eğer programın geri kalanı için çıkış tamponlama hakkında umursamazsak her baskı çağrısından sonra ya da sadece kullanım sys.stdout.flush (), aslında iyi olabilir)
Nicholas Şövalye

2
bu benim için çalışmıyor. Aslında bunu defalarca denedim ve benim için hiç işe yaramadı. Mac'te iterm2 kullanıyorum, ancak çoğu zaman bir linux sunucusuna ssh'dım. Bunu yapmak için gerçekten işe yarayan bir yöntem bulamadım.
bgenchel

33

Python 3.x'ten şunları yapabilirsiniz:

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

(Python 2.6 veya 2.7'de from __future__ import print_functionbetiğinizin / modülünüzün üstüne koyarak da kullanılabilir )

Python konsolu ilerleme çubuğu örneği:

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 da yeni bir satır
ekliyor

3
bu yeni satırdan kurtuluyor, ancak üzerine yazmaya izin vermiyor ki bence yazarın istediği şey bu.
bgenchel

1
@bgenchel '\ r' ile kullanıldı (kod örneğindeki gibi) tam olarak OP'nin istediğini yapıyor
Milo Wielondek

33

Benim için işe yarayan şey Remi ve siriusd'un cevaplarının bir kombinasyonuydu:

from __future__ import print_function
import sys

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

Güncel değil .. Python 3.8.5 itibariyle benim için sadece şu işe yarıyor: print ("some string", end = '\ r')
rroger

23

Python 3.3+ sürümünde ihtiyacınız yok sys.stdout.flush(). print(string, end='', flush=True)İşler.

Yani

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

"foo" nun üzerine "bar" yazar.


2
Basılı metnin bir "\r".
bli

13

Konsol için muhtemelen ihtiyacınız olacak

sys.stdout.flush()

güncellemeyi zorlamak için. Bence ,baskıda kullanmanın stdout'un temizlenmesini engelleyeceğini ve bir şekilde güncellenmeyeceğini düşünüyorum


Terminator, bu komutu print ifadesinden hemen sonra çalıştırmadığım sürece, benim için print ("...", end = '\ r') kullanırken her 30 saniyede bir satırı yeniliyordu. Teşekkürler
Bryce Guinta

4

Oyuna geç kaldım - ama cevapların hiçbiri benim için işe yaramadığı için (hepsini denemedim) ve bu cevabı aramamda bir kereden fazla buldum ... python 3'te, bu çözüm oldukça zarif ve bence yazarın tam olarak aradığı şeyi yapıyor, aynı satırda tek bir ifadeyi güncelliyor. Not, çizgi büyümek yerine küçülüyorsa özel bir şey yapmanız gerekebilir (örneğin ipi sonunda dolgulu boşluklarla sabit bir uzunlukta yapmak gibi)

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

1
python => 3.6 için en basit ve en temiz seçenek
DaveR

3

Bu benim için çalışıyor, mümkün olup olmadığını görmek için bir kez hacklendi, ancak programımda hiç kullanılmadı (GUI çok daha güzel):

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)

\bimlecin konumunu bir boşluk geri
hareket ettiririz Bu yüzden onu satırın başına kadar geri taşırız
Daha sonra mevcut satırı temizlemek için boşluklar yazarız - boşluklar yazarken imleç bir boşluk ileri / sağa hareket eder
Öyleyse sahip olduğumuz yeni verilerimizi yazmadan önce imleci satırın başına geri taşımak için

Python 2.7 kullanılarak Windows cmd'de test edilmiştir


1

Şöyle dene:

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

(Sonunda virgülle.)


Bu sadece yeni metni eskiye ekler (işlevsel olarak benzer ama çirkin).
chriscauley

1

Spyder kullanıyorsanız, çizgiler yalnızca önceki tüm çözümlerle sürekli olarak yazdırılır. Bundan kaçınmanın bir yolu şunları kullanmaktır:

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

Bu benim için çalışan tek çözümdü (Python 3.8, Windows, PyCharm).
z33k

1

Python 3+ için

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

0

Dayanarak Remi cevap için Python 2.7+kullanılmak bu:

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

İçin Python 3.6+ve herhangi listyerine sadece dahaint s yanı sıra yeni bir satıra geçmekten senin konsol penceresi tüm genişliğini kullanarak değil, aşağıdaki kullanabilirsiniz:

not: lütfen işlevin get_console_with()yalnızca Linux tabanlı sistemlerde çalışacağını ve bu nedenle Windows'ta çalışması için yeniden yazmanız gerektiğini unutmayın.

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

Python 3 kullanıyorsanız, bu sizin için ve gerçekten işe yarıyor.

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

0

Bir geri sayım göstermek için bunu kendi başıma anladım ama aynı zamanda bir yüzde için de işe yarayacak.

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

'/ R'den sonra gelen her şey bir önceki dizeyle aynı uzunlukta veya daha uzun (boşluklar dahil) olduğu sürece, aynı satırda onun üzerine yazacaktır. Sadece end = '' kısmını eklediğinizden emin olun, aksi takdirde yeni satıra yazdırılır. Umarım yardımcı olur!


0

StartRunning (), StopRunning (), boolean getIsRunning () ve getProgress100 () tamsayısını 0 ila 100 aralığında döndüren "pega" nesnesi için bu, çalıştırırken metin ilerleme çubuğu sağlar ...

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)

0

2020 sonu itibariyle ve Linux konsolunda Python 3.8.5 benim için sadece bu çalışıyor:

print('some string', end='\r')

Kredi: Bu gönderiye

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.