Önceki çıktının üzerine yazarak aynı satıra mı çıktı?


104

Bir FTP indirici yazıyorum. Kodun bir kısmı şuna benzer:

ftp.retrbinary("RETR " + file_name, process)

Geri aramayı işlemek için işlev sürecini arıyorum:

def process(data):
    print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    file.write(data)

ve çıktı şuna benzer:

1784  KB / KB 1829 downloaded!
1788  KB / KB 1829 downloaded!
etc...   

ancak bu satırı yazdırmasını ve bir dahaki sefere yeniden yazdırmasını / yenilemesini istiyorum, böylece yalnızca bir kez gösterecek ve bu indirmenin ilerlemesini göreceğim.

Nasıl yapılabilir?



Yanıtlar:


202

Python 3.x kodu:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!', end='\r')

end=Buradaki anahtar kelime çalışır budur - varsayılan olarak, print()bir satır (içinde biter \n) karakteri, ama bu farklı bir dize ile değiştirilebilir. Bu durumda, satırın satır başı ile bitirilmesi, bunun yerine imleci geçerli satırın başlangıcına döndürür. Bu nedenle, sysbu tür basit kullanım için modülü içe aktarmaya gerek yoktur . print()aslında kodu büyük ölçüde basitleştirmek için kullanılabilecek bir dizi anahtar kelime argümanı vardır.

Aynı kodu Python 2.6+ üzerinde kullanmak için aşağıdaki satırı dosyanın en üstüne koyun:

from __future__ import print_function

6
Baskı fonksiyonu da dosyanın en üstünde aşağıdaki ithalat ekleyerek 2.6+ python kullanılabileceğini Not: from __future__ import print_function.
janin

12
python <3.0'da ifadenin sonundaki virgül bir "\ n" önleyecektir: print "foo",Ancak değişikliği görmek için bundan sonra yine de sifonu çekmeniz gerekir:sys.stdout.flush()
Tobias Domhan

32
\rDizenin başına eklemem gerektiğini fark ettim ve end=''bunun yerine bunu işe yarayacak şekilde ayarladım . \r
Sonlandırdığımda

4
Tüm mevcut Python 3 sürümlerinde, arabelleğin temizlendiğinden emin olmak flush=Trueiçin print()işleve ekleyebilirsiniz (standart satır arabelleği yalnızca bir \nsatırsonu yazıldığında temizlenir ).
Martijn Pieters

4
Jüpiter bir defterde, \rbaşlangıçta ve end=''en iyi ve en sorunsuz şekilde çalıştı. Kullanımı flush=Trueile \rdize ve eğer sonunda end='\r'da çalıştı ama düzgün değildi ve çizgi & onun satır besleme sildi.
Dave X

41

Tek yapmak istediğiniz tek bir satırı değiştirmekse, kullanın \r. \rsatır başı anlamına gelir. Etkisi yalnızca imleci geçerli satırın başına geri koymaktır. Hiçbir şeyi silmez. Benzer şekilde, \bbir karakter geriye gitmek için kullanılabilir. (bazı terminaller tüm bu özellikleri desteklemeyebilir)

import sys

def process(data):
    size_str = os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    sys.stdout.write('%s\r' % size_str)
    sys.stdout.flush()
    file.write(data)

1
Bunun \rtaşıma dönüşü anlamına geldiğini ekleyeceğim . etkisi yalnızca imleci geçerli satırın başına geri koymaktır. hiçbir şeyi silmez. benzer şekilde, \bbir karakter geriye gitmek için kullanılabilir. (bazı terminaller bu özelliklerin tümünü desteklemeyebilir)
Adrien Plisson

sys.stdout.write('%s\r', size_str')Sanırım demek istedin sys.stdout.write('%s\r' % size_str)ama işe yaramıyor.
Kristian

@Adrien: Harika, bunu ekledi. @Kristian: Teşekkürler, güncelledi, oldukça geç oldu.
Sam Dolan

Ayrıca tercih ederseniz printbunun yerine kullanabileceğinizi de unutmayın sys.stdout.write: print size_str + "\r",iyi çalışıyor. ,Baskı deyimi sonunda yeni satırı bastırır; sys.stdout.flush()hala gerekli
Jeff

19

Göz at küfürler modülü dokümantasyon ve lanetler modülü NASIL'ı .

Gerçekten basit bir örnek:

import time
import curses

stdscr = curses.initscr()

stdscr.addstr(0, 0, "Hello")
stdscr.refresh()

time.sleep(1)

stdscr.addstr(0, 0, "World! (with curses)")
stdscr.refresh()

10
ne yazık ki curses sadece Unix'te mevcuttur. OP bize uygulamasının hangi işletim sistemini hedeflediğini söylemedi ...
Adrien Plisson

Linux altında çalışmaya o kadar alıştım ki, modül belgelerinde modülün sadece UNIX için olduğuna dair uyarıyı bile fark etmedim .. Bunu belirttiğiniz için teşekkürler @Adrien.
Andrea Spadaccini

3
@AdrienPlisson, bu sorunun yıllar önce yapıldığını biliyorum ama aslında Curses'i
Cold Diamondz

Bunu Python yorumlayıcıma yapıştırdığımda, terminalim fubar oldu. Tercümandan çıkmak yardımcı olmadı. O NE LAN?!
allyourcode

Kullanım clrtoeoliçin ikinci hat birinci az olunca.
Serge Stroobandt

9

İşte metin bloklarını yeniden basabilen küçük sınıfım. Önceki metni düzgün bir şekilde temizler, böylece eski metninizin üzerine daha kısa yeni metinler ile karışıklık yaratmadan yazabilirsiniz.

import re, sys

class Reprinter:
    def __init__(self):
        self.text = ''

    def moveup(self, lines):
        for _ in range(lines):
            sys.stdout.write("\x1b[A")

    def reprint(self, text):
        # Clear previous text by overwritig non-spaces with spaces
        self.moveup(self.text.count("\n"))
        sys.stdout.write(re.sub(r"[^\s]", " ", self.text))

        # Print new text
        lines = min(self.text.count("\n"), text.count("\n"))
        self.moveup(lines)
        sys.stdout.write(text)
        self.text = text

reprinter = Reprinter()

reprinter.reprint("Foobar\nBazbar")
reprinter.reprint("Foo\nbar")

2
Bu, Windows 10'a kadar Windows'ta çalışmayacaktır, çünkü Windows 10 bu kontrol karakterlerini destekleyen ilk penceredir en.wikipedia.org/wiki/ANSI_escape_code
user136036

8

Python 2.7'de basit bir print ifadesi için, sizin '\r'.

print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!\r',

Bu, diğer python 3 olmayan çözümlerden daha kısadır, ancak bakımı da daha zordur.


1
Python 2.7.10 ve hiçbir şey yazdırmıyor. Belki çevrimiçi olarak derleyebilir ve nasıl çalıştığını görmek için bize bir bağlantı gönderebilirsiniz ...?
Shougo Makishima

5

Dizenin sonuna '\ r' ve yazdırma işlevinin sonuna bir virgül ekleyebilirsiniz. Örneğin:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),

1
Bu python 3 için mi? Eğer öyleyse, varsayılan endparametre ile ne \nyazdırın (...)KB downloaded!\r\n. Yanlış mıyım?
SR

end = '\r'Bunun yerine kullanmak Python 3'teki sorunu düzeltir.
Abhimanyu Pallavi Sudhir

4

Spyder 3.3.1 - windows 7 - python 3.6 kullanıyorum, ancak floş gerekli olmayabilir. bu gönderiye göre - https://github.com/spyder-ide/spyder/issues/3437

   #works in spyder ipython console - \r at start of string , end=""
import time
import sys
    for i in range(20):
        time.sleep(0.5)
        print(f"\rnumber{i}",end="")
        sys.stdout.flush()

3

python'da önceki satırın üzerine yazmak için ihtiyacınız olan tek şey print fonksiyonuna end = '\ r' eklemektir , bu örneği test edin:

import time
for j in range(1,5):
   print('waiting : '+j, end='\r')
   time.sleep(1)
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.