Output ke baris yang sama menimpa output sebelumnya?

97

Saya sedang menulis pengunduh FTP. Bagian dari kode adalah seperti ini:

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

Saya memanggil proses fungsi untuk menangani panggilan balik:

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

dan keluarannya seperti ini:

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

tetapi saya ingin itu mencetak baris ini dan lain kali mencetak ulang / menyegarkannya sehingga itu hanya akan menampilkannya sekali dan saya akan melihat kemajuan unduhan itu.

Bagaimana caranya?

Kristian
sumber
Duplikat bilah kemajuan Teks di konsol .
Alexey
Kemungkinan duplikat Bilah Kemajuan Teks di Konsol
Alexey

Jawaban:

189

Berikut kode untuk Python 3.x:

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

Kata end=kunci adalah yang berfungsi di sini - secara default, print()diakhiri dengan karakter baris baru ( \n), tetapi ini dapat diganti dengan string yang berbeda. Dalam kasus ini, mengakhiri baris dengan carriage return akan mengembalikan kursor ke awal baris saat ini. Jadi, tidak perlu mengimpor sysmodul untuk penggunaan sederhana semacam ini. print()sebenarnya memiliki sejumlah argumen kata kunci yang dapat digunakan untuk menyederhanakan kode.

Untuk menggunakan kode yang sama pada Python 2.6+, letakkan baris berikut di bagian atas file:

from __future__ import print_function
Kudzu
sumber
6
Perhatikan bahwa fungsi cetak juga dapat digunakan dalam python 2.6+ dengan menambahkan impor berikut di bagian atas file: from __future__ import print_function.
janin
12
di python <3.0 koma di akhir pernyataan akan mencegah "\ n": print "foo",Namun Anda masih perlu membilas setelah itu untuk melihat perubahan:sys.stdout.flush()
Tobias Domhan
31
Saya menemukan saya perlu menyertakan \rdi awal string, dan mengatur end=''agar ini bekerja. Saya rasa terminal saya tidak suka jika saya akhiri dengan\r
Jezzamon
2
Dalam semua saat Python 3 rilis, Anda dapat menambahkan flush=Trueke print()fungsi untuk memastikan buffer memerah (garis standar penyangga hanya akan menyiram ketika \nbaris baru ditulis).
Martijn Pieters
4
Di notebook jupyter, menggunakan yang \rpaling awal dan end=''bekerja paling baik dan paling lancar. Menggunakan flush=Truedengan \rdi akhir jika string dan end='\r'juga bekerja tetapi tidak mulus & menghapus garis & linefeed nya.
Dave X
40

Jika yang ingin Anda lakukan hanyalah mengubah satu baris, gunakan \r. \rberarti kereta kembali. Efeknya hanya untuk menempatkan tanda sisipan kembali di awal baris saat ini. Itu tidak menghapus apapun. Demikian pula, \bdapat digunakan untuk mundur satu karakter. (beberapa terminal mungkin tidak mendukung semua fitur tersebut)

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)
Sam Dolan
sumber
1
saya akan menambahkan itu \rberarti kereta kembali. efeknya hanya untuk meletakkan tanda sisipan kembali di awal baris saat ini. itu tidak menghapus apapun. Demikian pula, \bdapat digunakan untuk mundur satu karakter. (beberapa terminal mungkin tidak mendukung semua fitur tersebut)
Adrien Plisson
sys.stdout.write('%s\r', size_str')Saya pikir Anda bermaksud sys.stdout.write('%s\r' % size_str)tetapi tidak berhasil.
Kristian
@Adrien: Keren, tambah itu. @Kristian: Terima kasih, perbarui itu, sudah sangat terlambat.
Sam Dolan
Juga perhatikan Anda masih dapat menggunakan printbukan sys.stdout.writejika Anda lebih memilih: print size_str + "\r",bekerja dengan baik. Di ,akhir pernyataan cetak menyembunyikan baris baru; sys.stdout.flush()masih dibutuhkan
Jeff
19

Silahkan lihat di dokumentasi kutukan modul dan kutukan HOWTO modul .

Contoh yang sangat mendasar:

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()
Andrea Spadaccini
sumber
10
sayangnya, kutukan hanya tersedia di Unix. OP tidak memberi tahu kami sistem operasi mana yang ditargetkan aplikasinya ...
Adrien Plisson
Saya sudah terbiasa bekerja di Linux sehingga saya bahkan tidak memperhatikan peringatan tentang modul yang hanya untuk UNIX di dokumen modul .. Terima kasih telah menunjukkannya, @Adrien.
Andrea Spadaccini
3
@AdrienPlisson, saya tahu bahwa pertanyaan ini dibuat bertahun-tahun yang lalu tetapi, Anda sebenarnya bisa mendapatkan Kutukan ke Windows: lfd.uci.edu/~gohlke/pythonlibs/#curses
Cold Diamondz
Ketika saya menempelkannya ke penerjemah Python saya, terminal saya menjadi fubar. Keluar dari penerjemah tidak membantu. WTF ?!
allyourcode
Gunakan clrtoeoluntuk saat baris kedua lebih pendek dari yang pertama.
Serge Stroobandt
9

Inilah kelas kecil saya yang bisa mencetak ulang blok teks. Ini benar membersihkan teks sebelumnya sehingga Anda dapat menimpa teks lama Anda dengan teks baru yang lebih pendek tanpa membuat kekacauan.

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")
Bouke Versteegh
sumber
2
Ini tidak akan berfungsi di Windows hingga Windows 10, karena Windows 10 adalah jendela pertama yang mendukung karakter kontrol tersebut en.wikipedia.org/wiki/ANSI_escape_code
user136036
8

Saya menemukan bahwa untuk pernyataan cetak sederhana di python 2.7, cukup beri koma di akhir setelah Anda '\r'.

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

Ini lebih pendek dari solusi non-python 3 lainnya, tetapi juga lebih sulit untuk dipelihara.

Matt Ellen
sumber
1
Python 2.7.10, dan tidak mencetak apa pun. Mungkin, Anda dapat menyusunnya secara online dan mengirimkan tautan kepada kami untuk melihat cara kerjanya ...?
Shougo Makishima
5

Anda bisa menambahkan '\ r' di akhir string ditambah koma di akhir fungsi cetak. Sebagai contoh:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),
Moustafa Saleh
sumber
1
Ini untuk python 3? Jika demikian bagaimana dengan endparameter default diatur ke \nso u print (...)KB downloaded!\r\n. Apakah aku salah?
SR
Menggunakan end = '\r'sebagai gantinya memperbaiki masalah di Python 3.
Abimanyu Pallavi Sudhir
4

Saya menggunakan spyder 3.3.1 - windows 7 - python 3.6 meskipun mungkin tidak diperlukan flush. berdasarkan posting ini - 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()
JoePythonKing
sumber
1

untuk menimpa baris sebelumnya di python semua yang Anda butuhkan adalah menambahkan end = '\ r' ke fungsi cetak, uji contoh ini:

import time
for j in range(1,5):
   print('waiting : '+j, end='\r')
   time.sleep(1)
Amirouche Zeggagh
sumber