Python'da konsol çıktısını değiştirin


106

Bazı C / C ++ programlarında olduğu gibi Python'da bu şık konsol sayaçlarından birini nasıl oluşturabileceğimi merak ediyorum.

Bir şeyler yapan bir döngüm var ve mevcut çıktı şu satırlar boyunca:

Doing thing 0
Doing thing 1
Doing thing 2
...

sadece son satır güncellemesine sahip olmak daha iyi ne olurdu;

X things done.

Bunu bir dizi konsol programında gördüm ve bunu Python'da yapıp yapmayacağımı / nasıl yapacağımı merak ediyorum.


3
Lanetlere bir göz atmalısın .
Björn Pollex

2
Sadece şunu kullanın print: stackoverflow.com/a/8436827/1959808
Ioannis Filippidis

1
@ BjörnPollex, cursesbir abartıdır (kabul edilen cevaba bakın).
Alexey

Yanıtlar:


151

Basit bir çözüm, "\r"dizeden önce yazmak ve bir satırsonu eklememektir; dizge asla kısalmazsa bu yeterlidir ...

sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()

Biraz daha karmaşık bir ilerleme çubuğu ... bu benim kullandığım bir şey:

def startProgress(title):
    global progress_x
    sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write("#" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write("#" * (40 - progress_x) + "]\n")
    sys.stdout.flush()

Sen çağrı startProgressoperasyonun açıklamasını geçerek sonra progress(x)nerede xnihayet yüzdesi ve olduğuendProgress()


2
Ya ip öncekinden daha kısaysa?
math2001

6
@ math2001 boşlukla doldurma.
felipsmartins

Kodun sadece ilk 2 satırına oy verildi. İlerleme çubuğu kısmı birkaç durumda yavaşlıyor. Yine de teşekkürler @ 6502
WaterRocket8236

Bazı programlar ( restic, flatpak) birkaç satır konsol çıktısını güncelleyebilir. Bunun nasıl başarılabileceğini şans eseri biliyor musun?
Alexey

1
@Alexey: imleci hareket ettirmek, ekranın bölümlerini temizlemek ve renkleri değiştirmek için ANSI kaçış kodlarını kullanabilirsiniz ... bkz. En.wikipedia.org/wiki/ANSI_escape_code
6502

39

Daha zarif bir çözüm şunlar olabilir:

def progressBar(current, total, barLength = 20):
    percent = float(current) * 100 / total
    arrow   = '-' * int(percent/100 * barLength - 1) + '>'
    spaces  = ' ' * (barLength - len(arrow))

    print('Progress: [%s%s] %d %%' % (arrow, spaces, percent), end='\r')

bu işlevi valueve ile çağırın endvalue, sonuç

Progress: [------------->      ] 69 %

Not: Python 2.x sürümü burada .


Halo'yu daha iyi ilerleme çubukları ve döndürücüler için kullanmalısınız .
Aravind Voggu

18

Gelen piton 3 aynı satırda yazdırmak için bunu yapabilirsiniz:

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

Özellikle en son güncelleme ve ilerlemeyi takip etmek için kullanışlıdır.

Bir döngünün ilerleyişini görmek istiyorsa , buradan tqdm'yi de tavsiye ederim . Geçerli yinelemeyi ve toplam yinelemeleri, beklenen bitirme süresiyle bir ilerleme çubuğu olarak yazdırır. Çok kullanışlı ve hızlı. Python2 ve python3 için çalışır.


7

Diğer cevap daha iyi olabilir, ama işte yaptığım şey. İlk olarak, backspace karakterini yazdıran ilerleme adında bir işlev yaptım:

def progress(x):
    out = '%s things done' % x  # The output
    bs = '\b' * 1000            # The backspace
    print bs,
    print out,

Daha sonra ana işlevimde bir döngüde şöyle çağırdım:

def main():
    for x in range(20):
        progress(x)
    return

Bu elbette tüm satırı silecektir, ancak tam olarak istediğinizi yapmak için onunla uğraşabilirsiniz. Bu yöntemi kullanarak bir ilerleme çubuğu oluşturdum.


4
Çalışır, ancak önceki satırda bir sonrakinden daha fazla karakter varsa, yeni satırın sonundan sonraki karakterler önceki satırdan kalır: "Yazım denetimi kaydı 417/701 [serfice yüzeye değişti], ne zaman] uminescence] cence] shmentarianism] "
Lil 'Bits

7

Bu yıl sonra tökezleyen herkes için (benim yaptığım gibi), 6502'nin yöntemlerinde ilerleme çubuğunun azalması ve artması için biraz ince ayar yaptım. Biraz daha fazla durumda kullanışlıdır. Harika bir araç için teşekkürler 6502!

Temel olarak, tek fark, progress (x) her çağrıldığında #s ve -s satırlarının tamamının yazılması ve imleç her zaman çubuğun başına döndürülmesidir.

def startprogress(title):
    """Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character"""
    global progress_x
    sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    """Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50"""
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    """End of progress bar;
    Write full bar, then move to next line"""
    sys.stdout.write("#" * 40 + "]\n")
    sys.stdout.flush()

1
Yine de, kod tarafından çok sık çağrılırsa bunun bazı yavaşlamalara neden olabileceğini buldum, bu yüzden sanırım YMMV
jat255

6

İyi anladıysam (emin değilim) kullanarak yazdırmak ister misiniz <CR>, değil <LR>mi?

Eğer öyleyse, bu mümkünse, konsol terminali buna izin verdiği sürece (çıktı si bir dosyaya yeniden yönlendirildiğinde bozulacaktır).

from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")

5

Baktığımız eğer sys kütüphane kullanmadan yapılabilir print()fonksiyonu

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

İşte kodum:

def update(n):
    for i in range(n):
        print("i:",i,sep='',end="\r",flush=True)
        #time.sleep(1)

5

Bunu bir süre önce yazdım ve onunla gerçekten mutlu oldum. Kullanmakta özgürsünüz.

Bir alır indexve totalve isteğe bağlı olarak titleya da bar_length. Bittiğinde, kum saatini bir onay işaretiyle değiştirir.

⏳ Calculating: [████░░░░░░░░░░░░░░░░░░░░░] 18.0% done

✅ Calculating: [█████████████████████████] 100.0% done

Test etmek için çalıştırılabilecek bir örnek ekledim.

import sys
import time

def print_percent_done(index, total, bar_len=50, title='Please wait'):
    '''
    index is expected to be 0 based index. 
    0 <= index < total
    '''
    percent_done = (index+1)/total*100
    percent_done = round(percent_done, 1)

    done = round(percent_done/(100/bar_len))
    togo = bar_len-done

    done_str = '█'*int(done)
    togo_str = '░'*int(togo)

    print(f'\t⏳{title}: [{done_str}{togo_str}] {percent_done}% done', end='\r')

    if round(percent_done) == 100:
        print('\t✅')


r = 50
for i in range(r):
    print_percent_done(i,r)
    time.sleep(.02)

Ayrıca, shutil.get_terminal_size()ilgiliyse kullanan terminal genişliğine bağlı olarak duyarlı ilerleme çubuğuna sahip bir sürümüm var .


4

Aravind Voggu örneğine biraz daha fazla işlevsellik eklendi :

def progressBar(name, value, endvalue, bar_length = 50, width = 20):
        percent = float(value) / endvalue
        arrow = '-' * int(round(percent*bar_length) - 1) + '>'
        spaces = ' ' * (bar_length - len(arrow))
        sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
                         name, width, arrow + spaces, int(round(percent*100))))
        sys.stdout.flush()
        if value == endvalue:     
             sys.stdout.write('\n\n')

Artık bir öncekini değiştirmeden birden fazla ilerleme çubuğu oluşturabilirsiniz.

Ayrıca namesabit genişlikte bir değer olarak ekledim .

İki döngü için ve iki kez progressBar()sonucun kullanımı şöyle görünecektir:

ilerleme çubuğu animasyonu


-1

Aşağıdaki kod, her 0,3 saniyede bir önceki sayının yerine 0'dan 137'ye kadar olan Mesajı sayacaktır.

Sahne arkasına giden sembol sayısı = basamak sayısı.

stream = sys.stdout
for i in range(137):
    stream.write('\b' * (len(str(i)) + 10))
    stream.write("Message : " + str(i))
    stream.flush()
    time.sleep(0.3)
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.